/* ==========================================================================
   BanqPipe landing — cinematic onramp
   Deep navy void, white type, electric ice + teal. Motion is additive: every
   element below is readable and positioned without JS and without animation.
   ========================================================================== */

/* "BanqPipe KR" is a glyph subset of Pretendard (OFL-1.1), renamed as the
   licence requires for modified copies. See assets/fonts/README-FONT.md. */
@font-face {
  font-family: "BanqPipe KR";
  src: url("../fonts/banqpipe-kr-400.woff2?v=20261002-bidi2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "BanqPipe KR";
  src: url("../fonts/banqpipe-kr-600.woff2?v=20261002-bidi2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "BanqPipe KR";
  src: url("../fonts/banqpipe-kr-800.woff2?v=20261002-bidi2") format("woff2");
  font-weight: 800;
  font-style: normal;
  font-display: swap;
}

:root {
  --void: #0c0a09;
  --void-2: #12100d;
  --text: #faf5eb;
  --text-dim: #c7bca9;
  --text-faint: #aa9c86;

  --ice: #efc778;
  --ice-strong: #e9ac45;
  --teal: #da8a36;
  --ink-on-ice: #261709;

  --surface: rgba(255, 255, 255, 0.042);
  --surface-2: rgba(255, 255, 255, 0.07);
  --line: rgba(255, 255, 255, 0.1);
  --line-strong: rgba(255, 255, 255, 0.2);

  --font-kr: "BanqPipe KR", -apple-system, BlinkMacSystemFont, "Apple SD Gothic Neo",
    "Noto Sans KR", "Malgun Gothic", sans-serif;
  --font-tech: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
    "Liberation Mono", monospace;

  --gutter: clamp(18px, 4.6vw, 56px);
  --shell: 1200px;
  --section-y: clamp(84px, 10vw, 150px);
  --radius: 26px;
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  background-color: var(--void);
}

body {
  margin: 0;
  min-height: 100%;
  background-color: var(--void);
  color: var(--text);
  font-family: var(--font-kr);
  font-size: clamp(16px, 15px + 0.18vw, 17.5px);
  font-weight: 400;
  line-height: 1.68;
  letter-spacing: -0.012em;
  word-break: keep-all;
  overflow-wrap: break-word;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, p, dl, dd, ol, ul, figure {
  margin: 0;
}
ol, ul {
  padding: 0;
  list-style: none;
}
a {
  color: inherit;
  text-decoration: none;
}
button, input, select {
  font: inherit;
  color: inherit;
}

:focus-visible {
  outline: 2px solid var(--ice);
  outline-offset: 3px;
  border-radius: 6px;
}

.shell {
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.skip-link {
  position: absolute;
  left: 14px;
  top: -70px;
  z-index: 120;
  padding: 11px 18px;
  border-radius: 10px;
  background: var(--ice);
  color: var(--ink-on-ice);
  font-size: 0.9rem;
  font-weight: 600;
  transition: top 180ms ease;
}
.skip-link:focus-visible {
  top: 14px;
}

/* --- backdrop ------------------------------------------------------------ */

.backdrop {
  position: fixed;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  pointer-events: none;
}
.backdrop > span {
  position: absolute;
  display: block;
}
.backdrop__horizon {
  inset: auto 0 -46% 0;
  height: 86%;
  background: radial-gradient(
    64% 100% at 50% 100%,
    rgba(233, 172, 69, 0.34) 0%,
    rgba(218, 138, 54, 0.14) 36%,
    rgba(12, 10, 9, 0) 72%
  );
}
.backdrop__beam {
  inset: -30% 0 auto auto;
  width: 76%;
  height: 86%;
  background: radial-gradient(48% 48% at 72% 28%, rgba(239, 199, 120, 0.2), rgba(12, 10, 9, 0) 70%);
  animation: beam-drift 54s ease-in-out infinite;
}
@keyframes beam-drift {
  0% {
    transform: translate3d(0, 0, 0) rotate(0deg);
  }
  50% {
    transform: translate3d(-22px, 16px, 0) rotate(4deg);
  }
  100% {
    transform: translate3d(0, 0, 0) rotate(0deg);
  }
}
.backdrop__dots {
  inset: 0;
  background-image: radial-gradient(circle, rgba(255, 255, 255, 0.075) 1px, rgba(0, 0, 0, 0) 1px);
  background-size: 28px 28px;
  -webkit-mask-image: radial-gradient(72% 58% at 50% 32%, #000 0%, rgba(0, 0, 0, 0) 78%);
  mask-image: radial-gradient(72% 58% at 50% 32%, #000 0%, rgba(0, 0, 0, 0) 78%);
  opacity: 0.85;
}
.backdrop__grain {
  inset: 0;
  opacity: 0.055;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23g)'/%3E%3C/svg%3E");
}

/* --- reveal (only exists when JS does) ----------------------------------- */

.js [data-reveal] {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 760ms cubic-bezier(0.2, 0.72, 0.2, 1),
    transform 760ms cubic-bezier(0.2, 0.72, 0.2, 1);
  transition-delay: var(--d, 0s);
  will-change: opacity, transform;
}
.js [data-reveal].is-in {
  opacity: 1;
  transform: none;
  will-change: auto;
}

/* --- shared bits --------------------------------------------------------- */

.kicker {
  display: flex;
  align-items: center;
  gap: 0.7em;
  font-family: var(--font-tech);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--ice);
}
.kicker__dot {
  width: 6px;
  height: 6px;
  flex: none;
  border-radius: 50%;
  background: var(--teal);
  box-shadow: 0 0 10px rgba(218, 138, 54, 0.9);
}

.wordmark {
  display: inline-flex;
  align-items: center;
  gap: 0.58em;
}
.wordmark__mark {
  width: 25px;
  height: 25px;
  flex: none;
  overflow: visible;
}
.wordmark--sm .wordmark__mark {
  width: 21px;
  height: 21px;
}
.mark__pipe {
  fill: none;
  stroke: var(--text);
  stroke-width: 5;
}
.mark__collar {
  fill: none;
  stroke: var(--text);
  stroke-width: 2.6;
  stroke-linecap: round;
}
.mark__drop {
  fill: var(--teal);
}
.wordmark__text {
  font-size: 1.12rem;
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1;
}
.wordmark--sm .wordmark__text {
  font-size: 0.98rem;
}

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

.head {
  position: relative;
  z-index: 20;
  padding-block: clamp(18px, 2.6vw, 30px);
}
.head__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
}
.head__inner > * {
  min-width: 0;
}
.head__nav {
  display: flex;
  align-items: center;
  flex: none;
  flex-wrap: nowrap;
  gap: clamp(10px, 2vw, 26px);
}
.head__link {
  display: inline-flex;
  align-items: center;
  min-height: 42px;
  padding-inline: 2px;
  font-size: 0.92rem;
  white-space: nowrap;
  color: var(--text-dim);
  transition: color 180ms ease;
}
.head__link:hover {
  color: var(--text);
}
.head__cta {
  display: inline-flex;
  align-items: center;
  min-height: 42px;
  padding: 0.62em 1.1em;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: var(--surface);
  font-size: 0.88rem;
  font-weight: 600;
  white-space: nowrap;
  transition: background-color 200ms ease, border-color 200ms ease;
}
.head__cta:hover {
  background: var(--surface-2);
  border-color: var(--ice);
}

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

.hero {
  padding-block: clamp(26px, 4vw, 54px) var(--section-y);
}
.hero__inner {
  display: grid;
  gap: clamp(44px, 6vw, 72px);
  align-items: center;
}

.hero__title {
  margin-top: clamp(18px, 2.4vw, 26px);
  font-size: clamp(2.8rem, 8.2vw, 5.1rem);
  font-weight: 800;
  line-height: 1.02;
  letter-spacing: -0.045em;
}
.hero__line {
  display: block;
}
.hero__line--accent {
  background: linear-gradient(96deg, var(--ice) 8%, var(--teal) 86%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.hero__lead {
  max-width: 34ch;
  margin-top: clamp(18px, 2.2vw, 26px);
  font-size: clamp(1rem, 1.2vw, 1.14rem);
  line-height: 1.66;
  color: var(--text-dim);
  text-wrap: pretty;
}
.hero__hint {
  margin-top: 1.1em;
  font-family: var(--font-tech);
  font-size: 0.78rem;
  letter-spacing: 0.01em;
  color: var(--text-faint);
}

/* --- hero orbit: portal, grid plane, metal coins ------------------------- */

/* The orbit deliberately bleeds past the stage so the portal can sit under and
   beside the card. `.hero` clips it, so none of that bleed is ever document
   overflow — the clip is the design, not a patch over a layout bug. */
.hero {
  overflow: clip;
}

.hero__copy,
.hero__stage {
  min-width: 0;
}
.hero__stage {
  position: relative;
}

.orbit {
  position: absolute;
  inset: -6% 0 -10% 0;
  z-index: 0;
  pointer-events: none;
}

/* dark receding plane — gives the hero depth instead of flat black */
.orbit__grid {
  position: absolute;
  inset: auto 0 0 0;
  height: 76%;
  background-image:
    repeating-linear-gradient(to right, rgba(239, 199, 120, 0.17) 0 1px, rgba(0, 0, 0, 0) 1px 58px),
    repeating-linear-gradient(to bottom, rgba(239, 199, 120, 0.13) 0 1px, rgba(0, 0, 0, 0) 1px 58px);
  transform-origin: 50% 100%;
  transform: perspective(540px) rotateX(74deg) scale(1.55);
  -webkit-mask-image: radial-gradient(74% 86% at 64% 96%, #000 6%, rgba(0, 0, 0, 0) 74%);
  mask-image: radial-gradient(74% 86% at 64% 96%, #000 6%, rgba(0, 0, 0, 0) 74%);
  opacity: 0.72;
  animation: grid-flow 9s linear infinite;
}
@keyframes grid-flow {
  from {
    transform: perspective(540px) rotateX(74deg) scale(1.55) translateY(0);
  }
  to {
    transform: perspective(540px) rotateX(74deg) scale(1.55) translateY(58px);
  }
}

/* the light the portal throws into the scene */
.orbit__bloom {
  position: absolute;
  right: 0;
  bottom: -6%;
  width: 96%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(
    closest-side,
    rgba(233, 172, 69, 0.3) 0%,
    rgba(218, 138, 54, 0.13) 48%,
    rgba(12, 10, 9, 0) 76%
  );
  /* Was a pointer-follow. Now it breathes on its own schedule — nothing on
     this page tracks the cursor. */
  animation: bloom-drift 46s ease-in-out infinite;
}
@keyframes bloom-drift {
  0% {
    transform: translate3d(0, 0, 0) scale(1);
  }
  50% {
    transform: translate3d(-14px, 11px, 0) scale(1.035);
  }
  100% {
    transform: translate3d(0, 0, 0) scale(1);
  }
}

/* luminous ice-blue portal, anchored lower-right behind the card */
.portal {
  position: absolute;
  border-radius: 50%;
  aspect-ratio: 1;
}
.portal--outer {
  right: -16%;
  bottom: -30%;
  width: 124%;
  border: 1px solid rgba(239, 199, 120, 0.16);
  box-shadow:
    0 0 90px 8px rgba(233, 172, 69, 0.12),
    inset 0 0 120px 12px rgba(233, 172, 69, 0.07);
}
.portal--inner {
  right: -4%;
  bottom: -16%;
  width: 92%;
  border: 1px solid rgba(239, 199, 120, 0.4);
  box-shadow:
    0 0 0 1px rgba(239, 199, 120, 0.08),
    0 0 70px 4px rgba(233, 172, 69, 0.26),
    inset 0 0 110px 14px rgba(233, 172, 69, 0.11);
}

/* the highlight that travels around the rim — a conic sweep masked to a hairline */
.portal__sheen {
  position: absolute;
  inset: -1px;
  border-radius: 50%;
  background: conic-gradient(
    from 190deg,
    rgba(239, 199, 120, 0) 0deg,
    rgba(239, 199, 120, 0.9) 34deg,
    rgba(255, 236, 190, 1) 56deg,
    rgba(218, 138, 54, 0.7) 82deg,
    rgba(239, 199, 120, 0) 140deg
  );
  -webkit-mask-image: radial-gradient(closest-side, rgba(0, 0, 0, 0) calc(100% - 3px), #000 calc(100% - 1.6px));
  mask-image: radial-gradient(closest-side, rgba(0, 0, 0, 0) calc(100% - 3px), #000 calc(100% - 1.6px));
  animation: portal-sweep 13s linear infinite;
}
@keyframes portal-sweep {
  to {
    transform: rotate(360deg);
  }
}

/* --- coins --------------------------------------------------------------- */

.orbit__field {
  position: absolute;
  inset: 0;
  /* A slow collective sway under the coins' own drift. Deliberately out of
     step with it (58s against 11-15s) so the group never pulses in sync. */
  animation: field-drift 58s ease-in-out infinite;
  /* The hero clips the orbit's bleed, which was shearing the upper coins into
     flat-topped half-discs at the nav boundary. Fading the top of the field
     means anything that does reach the clip line has already dissolved, so the
     cut is never a straight edge at any viewport height. */
  -webkit-mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 0) 0, #000 55px);
  mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 0) 0, #000 55px);
}

@keyframes field-drift {
  0% {
    transform: translate3d(0, 0, 0);
  }
  50% {
    transform: translate3d(17px, -13px, 0);
  }
  100% {
    transform: translate3d(0, 0, 0);
  }
}

.coin {
  position: absolute;
  display: block;
  perspective: 460px;
  filter: drop-shadow(0 18px 26px rgba(8, 6, 3, 0.85));
}
.coin__spin {
  display: block;
  transform-style: preserve-3d;
  animation: coin-turn var(--turn, 7s) ease-in-out infinite;
  animation-delay: var(--delay, 0s);
}
.coin__spin--full {
  animation-name: coin-revolve;
  animation-timing-function: linear;
}
.coin svg {
  display: block;
  width: 100%;
  height: auto;
}

/* a disc tilting about its own vertical axis reads as a coin turning in place */
@keyframes coin-turn {
  0%, 100% {
    transform: rotateY(-26deg) rotateZ(-3deg);
  }
  50% {
    transform: rotateY(26deg) rotateZ(3deg);
  }
}
@keyframes coin-revolve {
  to {
    transform: rotateY(360deg);
  }
}

/* and the whole coin drifts along the curve that leads into the portal */
@keyframes coin-drift {
  from {
    transform: translate3d(0, 0, 0);
  }
  to {
    transform: translate3d(var(--dx, 18px), var(--dy, 24px), 0);
  }
}

.coin--won {
  top: 7%;
  left: 0;
  width: clamp(54px, 8.4vw, 92px);
  --turn: 8.5s;
  --dx: 16px;
  --dy: 22px;
  animation: coin-drift 11s ease-in-out infinite alternate;
}
.coin--token {
  top: 40%;
  right: 1%;
  width: clamp(46px, 7vw, 78px);
  --turn: 7.4s;
  --delay: -2.6s;
  --dx: -14px;
  --dy: 20px;
  animation: coin-drift 13s ease-in-out infinite alternate;
}
.coin--disc {
  top: 9%;
  right: 16%;
  width: clamp(30px, 4.6vw, 52px);
  --turn: 16s;
  animation: coin-drift 15s ease-in-out infinite alternate;
  --dx: 20px;
  --dy: 18px;
}
.coin--chip {
  bottom: 6%;
  left: 14%;
  width: clamp(26px, 4vw, 44px);
  --turn: 6.2s;
  --delay: -1.4s;
  --dx: 26px;
  --dy: -16px;
  animation: coin-drift 12s ease-in-out infinite alternate;
}

.coin__edge {
  fill: url(#metalEdge);
}
.coin__face {
  fill: url(#metalFace);
}
.coin__face--teal {
  fill: url(#tealFace);
}
.coin__shade {
  fill: url(#metalShade);
}
.coin__rim {
  fill: none;
  stroke: url(#metalRim);
  stroke-width: 2.2;
}
.coin__spec {
  fill: none;
  stroke: rgba(255, 248, 225, 0.78);
  stroke-width: 3;
  stroke-linecap: round;
}
.coin__glyph {
  fill: none;
  stroke: rgba(47, 29, 13, 0.72);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.sprite {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

.is-paused,
.is-paused * {
  animation-play-state: paused !important;
}

/* --- swap card ----------------------------------------------------------- */

.swap {
  position: relative;
  z-index: 1;
  display: block;
  padding: clamp(18px, 2.4vw, 26px);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: linear-gradient(176deg, rgba(255, 255, 255, 0.082), rgba(255, 255, 255, 0.026));
  box-shadow: 0 46px 90px -46px rgba(0, 0, 0, 0.95),
    inset 0 1px 0 rgba(255, 255, 255, 0.14);
  -webkit-backdrop-filter: blur(20px);
  backdrop-filter: blur(20px);
}
.swap:focus {
  outline: none;
}

.swap__head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: clamp(14px, 1.8vw, 20px);
}
.swap__title {
  font-size: 1.02rem;
  font-weight: 700;
  letter-spacing: -0.03em;
}
.swap__flag {
  padding: 0.3em 0.7em;
  border: 1px solid rgba(253, 224, 71, 0.46);
  border-radius: 999px;
  background: rgba(253, 224, 71, 0.12);
  color: #fde68a;
  font-size: 0.72rem;
  font-weight: 600;
}
.swap__network {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-tech);
  font-size: 0.74rem;
  letter-spacing: 0.04em;
  color: var(--text-faint);
}
.network--static strong {
  color: var(--text-dim);
  font-weight: 600;
}
.network__select {
  padding: 0.35em 0.6em;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: var(--surface-2);
  font-family: var(--font-tech);
  font-size: 0.76rem;
}

.panel {
  position: relative;
  padding: clamp(15px, 1.9vw, 19px) clamp(15px, 1.9vw, 19px) clamp(13px, 1.6vw, 16px);
  border: 1px solid rgba(255, 255, 255, 0.075);
  border-radius: 18px;
  background: rgba(255, 255, 255, 0.035);
}
.panel + .panel {
  margin-top: 10px;
}
.panel__label {
  display: block;
  margin-bottom: 0.55em;
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--text-faint);
}
.panel__row {
  display: flex;
  align-items: center;
  gap: 12px;
}
.panel__input {
  flex: 1 1 auto;
  min-width: 0;
  font-size: clamp(1.75rem, 4.4vw, 2.3rem);
  font-weight: 800;
  letter-spacing: -0.04em;
  line-height: 1.18;
  font-feature-settings: "tnum" 1;
  font-variant-numeric: tabular-nums;
}
.panel__input {
  width: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  appearance: none;
}
.panel__input::placeholder {
  color: rgba(255, 255, 255, 0.22);
}
.panel__input:focus {
  outline: none;
}
.panel:focus-within {
  border-color: rgba(239, 199, 120, 0.5);
  box-shadow: 0 0 0 1px rgba(239, 199, 120, 0.26);
}
.panel__input:disabled {
  color: var(--text-faint);
  -webkit-text-fill-color: var(--text-faint);
}
[data-panel="USDT"] {
  background: rgba(239, 199, 120, 0.045);
  border-color: rgba(239, 199, 120, 0.14);
}
.panel__meta {
  margin-top: 0.5em;
  min-height: 1.2em;
  font-family: var(--font-tech);
  font-size: 0.72rem;
  letter-spacing: 0.02em;
  color: var(--text-faint);
}

.pill {
  display: inline-flex;
  align-items: center;
  gap: 0.42em;
  flex: none;
  padding: 0.46em 0.82em 0.46em 0.6em;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface-2);
  font-family: var(--font-tech);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.04em;
}
.pill__mark {
  display: inline-flex;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: rgba(239, 199, 120, 0.14);
}
.pill__mark svg {
  width: 100%;
  height: 100%;
  fill: none;
  stroke: var(--ice);
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.pill--out .pill__mark {
  background: rgba(218, 138, 54, 0.16);
}
.pill--out .pill__mark svg {
  stroke: var(--teal);
}

/* Both fields are editable, so the control between them reorders the stack
   rather than converting anything. The swap moves the panel nodes themselves
   (see toggleTop in swap.js) so the tab sequence and the screen-reader reading
   order follow what is on screen — `order` is deliberately not used here,
   because it would move the panels visually while leaving KRW first in the DOM. */
.swap__fields {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.swap__toggle {
  position: relative;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  margin: -19px auto;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: #1a1511;
  cursor: pointer;
  transition: border-color 180ms ease, background-color 180ms ease;
}
.swap__toggle:hover {
  border-color: rgba(239, 199, 120, 0.55);
  background: #211a14;
}
.swap__toggle svg {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: var(--ice);
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* A short settle after a swap — no FLIP, just a nudge into place. The global
   reduced-motion override collapses it to nothing. */
.swap__fields.is-swapping [data-panel] {
  animation: panel-settle 260ms cubic-bezier(0.2, 0.72, 0.2, 1);
}
@keyframes panel-settle {
  from {
    opacity: 0.45;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.swap__overshoot {
  margin-top: 10px;
  font-size: 0.8rem;
  line-height: 1.5;
  color: var(--ice);
}
.swap__overshoot[hidden] {
  display: none;
}

.presets {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  margin-top: 12px;
}
.preset {
  padding: 0.5em 0.9em;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: transparent;
  font-family: var(--font-tech);
  font-size: 0.76rem;
  cursor: pointer;
  transition: background-color 180ms ease, border-color 180ms ease, color 180ms ease;
}
.preset:hover {
  background: var(--surface-2);
  border-color: var(--line-strong);
}

.breakdown {
  margin-top: 12px;
  border: 1px solid rgba(255, 255, 255, 0.07);
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.022);
}
.breakdown__summary {
  padding: 0.72em 1em;
  font-size: 0.82rem;
  color: var(--text-dim);
  cursor: pointer;
  list-style: none;
}
.breakdown__summary::-webkit-details-marker {
  display: none;
}
.breakdown__summary::after {
  content: "+";
  float: right;
  color: var(--text-faint);
}
.breakdown[open] .breakdown__summary::after {
  content: "\2212";
}
.breakdown__list {
  padding: 0 1em 0.9em;
}
.breakdown__row {
  display: flex;
  justify-content: space-between;
  gap: 14px;
  padding: 0.32em 0;
  font-size: 0.82rem;
}
.breakdown__row dt {
  color: var(--text-faint);
}
.breakdown__row dd {
  font-family: var(--font-tech);
  font-size: 0.8rem;
  color: var(--text-dim);
  text-align: right;
}

.swap__status {
  min-height: 1.5em;
  margin-top: 13px;
  font-size: 0.84rem;
  line-height: 1.5;
  color: var(--text-dim);
}
.swap__status.is-empty {
  min-height: 0.8em;
}

.buy__label {
  display: inline-block;
}
.buy {
  display: block;
  width: 100%;
  margin-top: 13px;
  padding: 1.08em 1.2em;
  border: 0;
  border-radius: 16px;
  background: linear-gradient(104deg, var(--ice) 0%, var(--teal) 100%);
  color: var(--ink-on-ice);
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  cursor: pointer;
  box-shadow: 0 18px 38px -20px rgba(233, 172, 69, 0.8);
  transition: transform 200ms ease, box-shadow 200ms ease, filter 200ms ease;
}
.buy:not(:disabled):hover {
  transform: translateY(-1px);
  filter: brightness(1.06);
  box-shadow: 0 24px 46px -20px rgba(233, 172, 69, 0.9);
}
.buy:not(:disabled):active {
  transform: translateY(0);
}
.buy:disabled {
  background: rgba(255, 255, 255, 0.07);
  color: var(--text-faint);
  box-shadow: none;
  cursor: not-allowed;
}

.swap__note {
  margin-top: 11px;
  font-size: 0.78rem;
  line-height: 1.55;
  color: var(--text-faint);
}
.swap__caption {
  margin-top: 0.4em;
  font-family: var(--font-tech);
  font-size: 0.7rem;
  letter-spacing: 0.02em;
  color: var(--text-faint);
  opacity: 0.82;
}

.is-unavailable .panel__input,
.is-unavailable .pill {
  opacity: 0.55;
}

/* --- journey ------------------------------------------------------------- */

.journey {
  position: relative;
  padding-block: var(--section-y);
  border-top: 1px solid rgba(255, 255, 255, 0.07);
}
.journey__inner {
  display: block;
}
.journey__head {
  display: grid;
  gap: 0.7em;
}
.journey__title {
  font-size: clamp(1.7rem, 3.4vw, 2.5rem);
  font-weight: 800;
  line-height: 1.24;
  letter-spacing: -0.04em;
  text-wrap: pretty;
}

.stage {
  display: none;
}
.stage__art {
  width: 100%;
  max-width: 440px;
  height: auto;
  overflow: visible;
}

.stage__orbit ellipse {
  fill: none;
  stroke: rgba(239, 199, 120, 0.22);
  stroke-width: 1.2;
  transform-box: view-box;
  transform-origin: 210px 210px;
  transform: rotate(calc(var(--p, 0) * 150deg));
}
.stage__orbit ellipse:last-child {
  stroke: rgba(218, 138, 54, 0.2);
  stroke-dasharray: 2 10;
  transform: rotate(calc(var(--p, 0) * -210deg));
}

/* --s1/--s2 ramp across a whole stage, which left the previous scene hanging
   around at half opacity for most of the next one. --t1/--t2 compress that
   ramp into the first fifth of the stage, so the handoff is a brief, deliberate
   cross-fade at the boundary and the active art is then alone and fully opaque. */
.stage {
  --t1: clamp(0, calc(var(--s1, 0) * 5), 1);
  --t2: clamp(0, calc(var(--s2, 0) * 5), 1);
}

.scene {
  transform-box: view-box;
  transform-origin: 210px 210px;
}
.scene--0 {
  opacity: calc(1 - var(--t1));
  transform: translateY(calc(var(--t1) * -30px)) scale(calc(1 - var(--t1) * 0.08));
}
.scene--1 {
  opacity: calc(var(--t1) - var(--t2));
  transform: translateY(calc(30px * (1 - var(--t1)) - 30px * var(--t2)))
    scale(calc(0.94 + var(--t1) * 0.06 - var(--t2) * 0.06));
}
.scene--2 {
  opacity: var(--t2);
  transform: translateY(calc(30px * (1 - var(--t2)))) scale(calc(0.94 + var(--t2) * 0.06));
}

/* Belt and braces off the real, observable stage index: a scene two steps away
   from the active one is never drawn, whatever the scrub variables say. */
.stage[data-stage="0"] .scene--2,
.stage[data-stage="2"] .scene--0 {
  opacity: 0;
}

.sk-field {
  fill: rgba(255, 255, 255, 0.04);
  stroke: rgba(255, 255, 255, 0.17);
  stroke-width: 1.6;
}
.sk-field--soft {
  fill: rgba(255, 255, 255, 0.022);
  stroke: rgba(255, 255, 255, 0.11);
}
.sk-mark {
  fill: rgba(239, 199, 120, 0.16);
  stroke: var(--ice);
  stroke-width: 1.6;
}
.sk-glyph {
  fill: none;
  stroke: var(--ice);
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.sk-line {
  fill: none;
  stroke: rgba(255, 255, 255, 0.4);
  stroke-width: 3;
  stroke-linecap: round;
}
.sk-line--faint {
  stroke: rgba(255, 255, 255, 0.16);
  stroke-width: 1.4;
}
.sk-caret {
  fill: none;
  stroke: var(--teal);
  stroke-width: 2.4;
  stroke-linecap: round;
}
.sk-dot {
  fill: rgba(218, 138, 54, 0.3);
  stroke: var(--teal);
  stroke-width: 1.5;
}
.sk-spark {
  fill: rgba(239, 199, 120, 0.4);
}
.sk-dash {
  fill: none;
  stroke: var(--ice);
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-dasharray: 5 9;
}
.sk-flow {
  fill: none;
  stroke: var(--teal);
  stroke-width: 2.6;
  stroke-linecap: round;
  stroke-dasharray: 6 8;
}
.sk-token {
  fill: rgba(218, 138, 54, 0.14);
  stroke: var(--teal);
  stroke-width: 2;
  stroke-linejoin: round;
}
.sk-ray {
  fill: none;
  stroke: rgba(239, 199, 120, 0.55);
  stroke-width: 2.2;
  stroke-linecap: round;
}

.rail {
  display: none;
}
.rail__item {
  display: flex;
  align-items: baseline;
  gap: 0.8em;
  padding: 0.5em 0;
  color: var(--text-faint);
  transition: color 240ms ease;
}
.rail__num {
  font-family: var(--font-tech);
  font-size: 0.74rem;
  letter-spacing: 0.1em;
}
.rail__name {
  font-size: 0.9rem;
}
.rail__item.is-active,
.rail__item:hover {
  color: var(--text);
}

.track {
  display: grid;
  gap: clamp(44px, 6vw, 68px);
  margin-top: clamp(38px, 5vw, 56px);
}
.track__num {
  display: block;
  font-family: var(--font-tech);
  font-size: 0.8rem;
  letter-spacing: 0.18em;
  color: var(--ice);
}
.track__title {
  margin-top: 0.5em;
  font-size: clamp(1.18rem, 2vw, 1.45rem);
  font-weight: 700;
  letter-spacing: -0.035em;
  line-height: 1.38;
}
.track__text {
  max-width: 44ch;
  margin-top: 0.6em;
  font-size: 0.96rem;
  line-height: 1.7;
  color: var(--text-dim);
  text-wrap: pretty;
}

.mini {
  display: block;
  max-width: 300px;
  margin-top: 1.4em;
}
.mini svg {
  width: 100%;
  height: auto;
  display: block;
}

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

.closing {
  padding-block: 0 var(--section-y);
}
.closing__inner {
  display: grid;
  justify-items: start;
  gap: 0.9em;
  padding: clamp(28px, 4vw, 52px);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: linear-gradient(170deg, rgba(255, 255, 255, 0.06), rgba(255, 255, 255, 0.02));
}
.closing__title {
  max-width: 24ch;
  font-size: clamp(1.4rem, 2.8vw, 2.05rem);
  font-weight: 800;
  line-height: 1.3;
  letter-spacing: -0.04em;
  text-wrap: pretty;
}
.closing__text {
  font-size: 0.95rem;
  color: var(--text-dim);
}
.closing__cta {
  margin-top: 0.6em;
  padding: 0.92em 1.6em;
  border-radius: 14px;
  background: linear-gradient(104deg, var(--ice) 0%, var(--teal) 100%);
  color: var(--ink-on-ice);
  font-size: 0.96rem;
  font-weight: 700;
  box-shadow: 0 18px 38px -22px rgba(233, 172, 69, 0.8);
  transition: transform 200ms ease, filter 200ms ease;
}
.closing__cta:hover {
  transform: translateY(-1px);
  filter: brightness(1.06);
}

/* --- footer -------------------------------------------------------------- */

.foot {
  padding-block: clamp(22px, 3vw, 34px) clamp(30px, 4vw, 46px);
  border-top: 1px solid rgba(255, 255, 255, 0.07);
}
.foot__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
}
.foot__label {
  font-family: var(--font-tech);
  font-size: 0.76rem;
  letter-spacing: 0.1em;
  color: var(--text-faint);
}

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

@media (min-width: 760px) {
  .presets {
    gap: 8px;
  }
}

/* Mobile keeps the scene but pays less for it: half the coins, a still grid
   and no conic sweep repaint. */
@media (max-width: 899px) {
  .coin--disc,
  .coin--chip {
    display: none;
  }
  .orbit__grid {
    animation: none;
    opacity: 0.5;
  }
  .portal--outer {
    display: none;
  }
}

/* 320 px: the two nav items have to stay on one line beside the wordmark. */
@media (max-width: 480px) {
  .wordmark {
    gap: 0.45em;
  }
  .wordmark__mark {
    width: 22px;
    height: 22px;
  }
  .wordmark__text {
    font-size: 1rem;
  }
  .head__inner {
    gap: 10px;
  }
  .head__nav {
    gap: 9px;
  }
  .head__link {
    font-size: 0.82rem;
  }
  .head__cta {
    padding: 0.56em 0.82em;
    font-size: 0.8rem;
  }
}

@media (min-width: 900px) {
  .hero__inner {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.04fr);
    gap: clamp(40px, 5vw, 86px);
  }
  .orbit {
    inset: -8% -24% -22% -6%;
  }
  .hero__lead {
    max-width: 30ch;
  }
  .swap {
    padding: clamp(22px, 1.9vw, 28px);
  }

  .js .journey__inner {
    display: grid;
    grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
    gap: clamp(40px, 5vw, 92px);
    align-items: start;
  }
  .js .journey__col {
    position: sticky;
    top: 0;
    height: 100vh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: clamp(22px, 2.6vw, 36px);
  }
  .js .stage {
    display: block;
  }
  /* The pinned column is exactly 100vh, and the artwork is the only part of it
     that can give. At 1440x720 the heading + 440px art + rail + two gaps came
     to ~730px, so the heading top and the last rail item were clipped. Bounding
     the art by the height left over after that fixed chrome (~282px measured,
     330px allowed for a taller wrapped heading) keeps the stack inside the pin.
     The 440px cap still wins on anything from ~770px tall upward, so the
     1000px-tall design is untouched; the floor stops the art collapsing on very
     short windows. The SVG is square, so capping the width caps the height. */
  .js .stage__art {
    max-width: min(440px, max(200px, calc(100vh - 330px)));
  }
  .js .rail {
    display: grid;
    gap: 2px;
  }
  .js .mini {
    display: none;
  }
  .js .track {
    margin-top: 0;
    gap: 0;
  }
  .js .track__step {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    justify-content: center;
  }

  .closing__inner {
    justify-items: start;
  }
}

@media (min-width: 1100px) {
  .hero {
    padding-block: clamp(34px, 4vw, 70px) var(--section-y);
  }
}

/* --- motion & contrast preferences --------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
  }
  .js [data-reveal] {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .js .journey__inner {
    display: block;
  }
  .js .journey__col {
    position: static;
    height: auto;
    display: block;
  }
  .js .stage {
    display: none;
  }
  .js .rail {
    display: none;
  }
  .js .mini {
    display: block;
  }
  .js .track {
    margin-top: clamp(38px, 5vw, 56px);
    gap: clamp(44px, 6vw, 68px);
  }
  .js .track__step {
    min-height: 0;
    display: block;
  }
}

@media (prefers-contrast: more) {
  :root {
    --text-dim: #eee3cd;
    --text-faint: #ded1b9;
    --line: rgba(255, 255, 255, 0.28);
    --line-strong: rgba(255, 255, 255, 0.46);
  }
}
