/* ==========================================================================
   SNOWPOOLS
   #1A1A1B — the prism component's own ground, with the prism rendering its
   full spectrum untouched behind everything. Text and marks take Uniswap's
   palette instead, anchored on the unicorn's #ff007a. Snow stays, in white.
   Plus Jakarta Sans throughout · JetBrains Mono (data)
   Everything lowercase. Tight tracking. Wide air between sections.
   ========================================================================== */

@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap');

:root {
  --bg: #1a1a1b;
  --ink: #ffffff;
  --ink-2: rgba(255, 255, 255, 0.62);
  --ink-3: rgba(255, 255, 255, 0.4);
  --ink-4: rgba(255, 255, 255, 0.24);

  /* Uniswap's palette, anchored on the unicorn's #ff007a and walked in one
     direction only — pink into magenta into violet into the cornflower blue
     off their banner, then back to rose. No yellow: it is the one hue in a
     prism that cannot sit next to this pink without souring it, and it broke
     the arc every time it came round. A prism reads as a prism because the
     hues are *ordered*, not because all of them are present. */
  --uni-pink: #ff007a;
  --uni-magenta: #ff37c7;
  --uni-orchid: #d96bff;
  --uni-violet: #9d7bff;
  --uni-corn: #7ba8ff;
  --uni-rose: #ff8fd0;
  --accent: var(--uni-pink);

  --line: rgba(255, 255, 255, 0.09);
  --line-2: rgba(255, 255, 255, 0.16);
  --card: rgba(249, 249, 249, 0.05);

  --f: 'Plus Jakarta Sans', system-ui, -apple-system, sans-serif;
  --f-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;

  --gutter: 24px;
  --max: 1080px;
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--f);
  font-size: 16px;
  line-height: 1.6;
  letter-spacing: -0.01em;
  text-transform: lowercase;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

/* addresses and hashes must never be lowercased — checksums carry meaning */
.mono, code, .addr { text-transform: none; font-family: var(--f-mono); }

a { color: inherit; text-decoration: none; }
h1, h2, h3, p { margin: 0; }

/* ---------- background: snow layer ----------------------------------------
   A CSS placeholder until the loop video lands in media/snow-loop.mp4.
   Drop the file in and #snow-video takes over — the CSS layer hides itself.
   -------------------------------------------------------------------------- */

.bg {
  position: fixed;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  background: var(--bg);
}

/* The prism renders exactly as its author intended: additive glow on a dark
   ground, no blend mode, no filter, nothing recolouring it. Both of those
   would also blank the page on scroll from inside this fixed z-index:-1
   layer, which is how we found out the hard way. */
.bg canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  z-index: 0;
}

/* A scrim between the shader and the page. The prism's bright bands swing
   from near-black to near-white, and body copy cannot survive that range —
   the demo only gets away with it because it has a single glass card. This
   keeps the spectrum visible and gives the text a floor to sit on. */
.bg::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: rgba(26, 26, 27, 0.46);
}

.bg video, .snow { z-index: 2; }

.bg video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 1.2s var(--ease);
}
.bg video.ready { opacity: 0.55; }
.bg.has-video .snow { display: none; }

/* Falling snow: three tiled layers at different densities, sizes and speeds.
   Depth comes from the layers disagreeing with each other — one dense layer
   would read as noise, not as weather. */
.snow {
  position: absolute;
  inset: -30% -15%;
  background-image:
    radial-gradient(2.4px 2.4px at 20% 10%, rgba(255,255,255,.95), transparent 60%),
    radial-gradient(1.8px 1.8px at 62% 34%, rgba(255,255,255,.85), transparent 60%),
    radial-gradient(2px 2px at 84% 12%, rgba(255,255,255,.9), transparent 60%),
    radial-gradient(1.5px 1.5px at 38% 68%, rgba(255,255,255,.8), transparent 60%),
    radial-gradient(2.2px 2.2px at 8% 52%, rgba(255,255,255,.9), transparent 60%),
    radial-gradient(1.6px 1.6px at 72% 82%, rgba(255,255,255,.85), transparent 60%),
    radial-gradient(1.9px 1.9px at 46% 22%, rgba(255,255,255,.85), transparent 60%),
    radial-gradient(1.4px 1.4px at 92% 58%, rgba(255,255,255,.8), transparent 60%),
    radial-gradient(2.1px 2.1px at 28% 90%, rgba(255,255,255,.9), transparent 60%),
    radial-gradient(1.6px 1.6px at 56% 6%, rgba(255,255,255,.8), transparent 60%);
  background-size: 300px 300px;
  animation: fall 24s linear infinite;
  will-change: transform;
}

/* mid layer — bigger tile, slower, drifts further sideways */
.snow.b {
  background-size: 440px 440px;
  opacity: .72;
  animation-duration: 38s;
  animation-name: fall-b;
}

/* far layer — small, faint, almost vertical */
.snow.c {
  background-size: 620px 620px;
  opacity: .5;
  animation-duration: 56s;
  animation-name: fall-c;
  filter: blur(.4px);
}

@keyframes fall {
  from { transform: translate3d(0, -300px, 0); }
  to   { transform: translate3d(-70px, 300px, 0); }
}
@keyframes fall-b {
  from { transform: translate3d(0, -440px, 0); }
  to   { transform: translate3d(-130px, 440px, 0); }
}
@keyframes fall-c {
  from { transform: translate3d(0, -620px, 0); }
  to   { transform: translate3d(-40px, 620px, 0); }
}

@media (prefers-reduced-motion: reduce) {
  .snow { animation: none; }
}

/* ---------- header ---------- */

.hdr {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 40;
  padding: 22px var(--gutter);
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: linear-gradient(to bottom, rgba(26,26,27,.86), rgba(26,26,27,0));
  backdrop-filter: blur(6px);
}

.wordmark {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-weight: 800;
  font-size: 17px;
  letter-spacing: -0.04em;
}
/* The gap belongs between the mark and the name — not inside the name. A bare
   text node beside a <span> is two flex items, and the gap lands in the
   middle of the word.
   One colour, like the hero: the two-tone white/blue split is gone. */
.wordmark-text {
  font-family: var(--f);
  text-transform: uppercase;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.11em;
  color: var(--ink);
}
.mark { flex: none; display: block; }

/* ---------- the flake, as a pixel display ----------
   Built by assets/flake3d.js, which samples the mark's geometry onto a grid
   and lights the cells that land on it. The unlit cells stay, faintly: the
   dark grid behind the shape is what makes it read as a panel rather than as
   an illustration. The whole thing then turns in a preserve-3d scene, so it
   is a screen being rotated. */

.f3 {
  width: var(--size);
  height: var(--size);
  perspective: 900px;
  perspective-origin: 50% 46%;
}

.f3-spin {
  position: relative;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  /* The tilt is held while the spin runs, so the panel is never seen dead
     flat — a plane viewed at exactly 90 degrees would vanish. */
  animation: f3-turn 26s linear infinite;
}
@keyframes f3-turn {
  from { transform: rotateX(-16deg) rotateY(0deg); }
  to   { transform: rotateX(-16deg) rotateY(360deg); }
}

.f3-panel {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
}

.f3-panel i {
  position: absolute;
  width: var(--px);
  height: var(--px);
  display: block;
  /* Square cells, one pixel of rounding. Circles would read as a bead
     curtain; squares read as a display. */
  border-radius: 1px;
}
.f3-panel i.off { background: #ffffff; }

.f3-core {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  /* A pinpoint, not a lamp. */
  background: radial-gradient(
    circle,
    rgba(255, 255, 255, 0.75) 0%,
    rgba(255, 143, 208, 0.26) 22%,
    rgba(217, 107, 255, 0) 58%
  );
  pointer-events: none;
}

/* No coloured bloom around the object. The background is already made of
   light, so adding more only produced a sticker with a glow behind it — the
   pixels do their own glowing, individually, which is the point. */
.f3 { filter: drop-shadow(0 10px 22px rgba(0, 0, 0, 0.5)); }

@media (prefers-reduced-motion: reduce) {
  .f3-spin { animation: none; transform: rotateX(-16deg) rotateY(-24deg); }
}

/* The light travels around the flake the way it travels through the prism:
   each arm brightens a beat after the one before it, one full turn every
   seven seconds. */
.arms use {
  animation: arm 7s var(--ease) infinite;
}
.arms use:nth-child(2) { animation-delay: -1.16s; }
.arms use:nth-child(3) { animation-delay: -2.33s; }
.arms use:nth-child(4) { animation-delay: -3.5s; }
.arms use:nth-child(5) { animation-delay: -4.66s; }
.arms use:nth-child(6) { animation-delay: -5.83s; }

@keyframes arm {
  0%, 100% { opacity: 1; }
  40%      { opacity: .45; }
}

/* the flake itself turns, slowly enough to read as drift rather than spin */
.flake .arms {
  transform-origin: 50% 50%;
  animation: turn 64s linear infinite;
}
@keyframes turn { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
  .arms use, .flake .arms { animation: none; }
}

.nav {
  display: flex;
  align-items: center;
  gap: 26px;
  font-size: 14.5px;
  color: var(--ink-3);
}
.nav a { transition: color .25s var(--ease); }
.nav a:hover, .nav a[aria-current="page"] { color: var(--ink); }
.nav a.accent { color: var(--accent); }

.icon { display: inline-flex; color: var(--ink-3); transition: color .25s var(--ease); }
.icon:hover { color: var(--ink); }

.status { display: inline-flex; align-items: center; gap: 8px; color: var(--ink-3); font-size: 14.5px; }
.dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 4px rgba(74,216,255,.16);
  animation: pulse 2.6s var(--ease) infinite;
}
@keyframes pulse { 50% { box-shadow: 0 0 0 8px rgba(74,216,255,0); } }

.ticker {
  font-family: var(--f-mono);
  text-transform: none;
  font-size: 12.5px;
  color: rgba(255, 255, 255, 0.82);
  border: 1px solid var(--line-2);
  border-radius: 999px;
  padding: 3px 10px;
}

@media (max-width: 820px) {
  .nav .hide-sm { display: none; }
  .nav { gap: 16px; }
}

/* Below this the section links do not fit alongside the ticker, and pushing
   them off the edge under overflow-x:hidden would take the ticker with them.
   They stay reachable in the footer; the header keeps X and the ticker. */
@media (max-width: 720px) {
  .nav a[href^="#"] { display: none; }
}

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

.wrap { max-width: var(--max); margin: 0 auto; padding: 0 var(--gutter); }

section { padding: 128px var(--gutter); }
section .wrap { padding: 0; }

.sep { display: flex; justify-content: center; padding: 32px 0; }
.sep::before {
  content: "";
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--ink-4);
}

/* ---------- hero ---------- */

.hero {
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding-top: 96px;
}

/* Lifted from the component's own showcase card, with its corner radius kept
   — it is the one round thing on a page of square corners, and it earns it by
   being the only element that has to sit directly on the shader. */
.glass {
  display: flex;
  flex-direction: column;
  align-items: center;
  /* Sized to what is actually in it. These numbers were set when the card
     still held a large title; keeping them afterwards left it padded around
     half the content. */
  padding: 38px 48px 40px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 40px;
  background: rgba(249, 249, 249, 0.05);
  backdrop-filter: blur(22px);
  -webkit-backdrop-filter: blur(22px);
  box-shadow: 0 40px 100px rgba(0, 0, 0, 0.4);
}
@media (max-width: 640px) {
  .glass { padding: 30px 22px 32px; border-radius: 26px; }
}

/* Unused while the name lives only in the header. Kept because it is the
   whole of the alternative: put `<h1 class="h1">SNOWPOOLS</h1>` back at the
   top of .glass and the name returns to the middle, already harmonised —
   same family and nearly the same weight as the line under it, at 88% white
   rather than pure, so it reads as the same material as the paragraph. */
.h1 {
  font-family: var(--f);
  text-transform: uppercase;
  font-size: clamp(26px, 4.3vw, 45px);
  font-weight: 600;
  letter-spacing: 0.052em;
  line-height: 1.05;
  color: rgba(255, 255, 255, 0.88);
}

/* The tagline keeps its capitals too. Everything else on the page is
   lowercase by design, so sentence case is what makes this read as a
   sentence rather than as another label. */
.lede {
  text-transform: none;
  margin-top: 30px;
  max-width: 38ch;
  font-size: clamp(17px, 2.2vw, 20px);
  color: var(--ink-2);
  line-height: 1.5;
}

/* In the hero it keeps its normal size and weight — being the first line said
   does not entitle it to be bigger. Only the top margin goes, since there is
   no longer a title above it to be spaced from. */
.glass .lede { margin-top: 0; }

/* 64px here was the distance from a title-plus-paragraph block. Against the
   paragraph alone it read as a hole in the middle of the card. */
.ca { margin-top: 30px; }
.ca .label {
  font-size: 11px;
  letter-spacing: 0.22em;
  color: var(--ink-3);
  text-transform: uppercase;
}
.ca .addr {
  margin-top: 10px;
  font-size: 14px;
  color: var(--ink-2);
  word-break: break-all;
  max-width: 26ch;
  cursor: pointer;
  transition: color .25s var(--ease);
}
.ca .addr:hover { color: var(--accent); }

/* ---------- type ---------- */

.h2 {
  font-size: clamp(30px, 5vw, 46px);
  font-weight: 700;
  letter-spacing: -0.035em;
  line-height: 1.05;
}

.eyebrow {
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 22px;
}

.body {
  font-size: clamp(16px, 2vw, 18px);
  color: var(--ink-2);
  line-height: 1.62;
  max-width: 62ch;
}
.body + .body { margin-top: 20px; }

.center { text-align: center; }
.center .body, .center .lede { margin-left: auto; margin-right: auto; }

/* ---------- numbers ---------- */

.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 48px 24px;
  text-align: center;
}
.stat .n {
  font-size: clamp(38px, 6vw, 62px);
  font-weight: 800;
  letter-spacing: -0.04em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.stat .n.ice { color: var(--accent); }
/* an em dash at 800 weight reads as a solid black bar — while a counter is
   still empty it should look like an absence, not a redaction */
.stat .n.dash { font-weight: 400; color: var(--ink-4); }
.stat .k {
  margin-top: 12px;
  font-size: 13px;
  color: var(--ink-3);
}

/* the burn bar — the one piece of chrome on the page */
.bar {
  margin: 56px auto 0;
  max-width: 620px;
  height: 3px;
  background: var(--line);
  border-radius: 999px;
  overflow: hidden;
}
.bar i {
  display: block;
  height: 100%;
  width: 0;
  background: linear-gradient(90deg, var(--uni-orchid), var(--uni-pink));
  transition: width 1.6s var(--ease);
}

/* ---------- steps ---------- */

.steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 40px 32px;
  margin-top: 56px;
}
.step .i {
  font-family: var(--f-mono);
  font-size: 12px;
  color: var(--accent);
  text-transform: none;
}
.step h3 {
  margin-top: 14px;
  font-size: 19px;
  font-weight: 700;
  letter-spacing: -0.025em;
}
.step p { margin-top: 10px; font-size: 15.5px; color: var(--ink-2); line-height: 1.55; }

/* ---------- rules table ---------- */

.rules { margin-top: 48px; border-top: 1px solid var(--line); }
.rule {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 24px;
  padding: 18px 0;
  border-bottom: 1px solid var(--line);
  font-size: 15.5px;
}
.rule dt { color: var(--ink-3); }
.rule dd { margin: 0; text-align: right; color: var(--ink); }
.rule dd.addr { font-size: 13.5px; word-break: break-all; }

/* ---------- launch panel ---------- */

.panel {
  margin-top: 48px;
  border: 1px solid var(--line-2);
  border-radius: 4px;
  background: var(--card);
  backdrop-filter: blur(10px);
  padding: 40px;
}
@media (max-width: 640px) { .panel { padding: 28px 20px; } }

.field { margin-top: 22px; }
.field label { display: block; font-size: 13px; color: var(--ink-3); margin-bottom: 8px; }
.field input {
  width: 100%;
  font: inherit;
  font-size: 15px;
  color: var(--ink);
  background: rgba(255,255,255,.05);
  border: 1px solid var(--line-2);
  border-radius: 3px;
  padding: 12px 14px;
  outline: none;
  transition: border-color .25s var(--ease);
}
.field input::placeholder { color: var(--ink-4); }
.field input:focus { border-color: var(--accent); }

.row { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
@media (max-width: 560px) { .row { grid-template-columns: 1fr; } }

.btn {
  margin-top: 28px;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font: inherit;
  font-size: 15px;
  font-weight: 600;
  /* the demo's white pill, squared off to match everything else here */
  color: #111;
  background: #fff;
  border: 0;
  border-radius: 3px;
  padding: 13px 22px;
  cursor: pointer;
  transition: background .25s var(--ease), opacity .25s var(--ease);
}
.btn:hover { background: var(--uni-pink); color: #fff; }
.btn[disabled] { opacity: .32; cursor: not-allowed; background: #fff; }

.note {
  margin-top: 16px;
  font-size: 13.5px;
  color: var(--ink-3);
}

/* ---------- closing ---------- */

.closing { padding: 176px var(--gutter); text-align: center; }
.closing .h2 { line-height: 1.02; }
.closing .h2 span { color: var(--accent); }

footer {
  padding: 44px var(--gutter) 56px;
  text-align: center;
  color: var(--ink-3);
  font-size: 14px;
  border-top: 1px solid var(--line);
}
footer nav { display: flex; gap: 22px; justify-content: center; }
footer nav a:hover { color: var(--ink); }
footer .fine { margin-top: 22px; font-size: 12.5px; color: var(--ink-4); max-width: 56ch; margin-inline: auto; }

/* ---------- reveal ---------- */

.rv { opacity: 0; transform: translateY(14px); transition: opacity .9s var(--ease), transform .9s var(--ease); }
.rv.in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) { .rv { opacity: 1; transform: none; } }
