/* THE DAG RAIL — horizontal travel driven by vertical scroll.

   Everything here is scoped to .is-railed, which the script adds only when
   the rail is actually running. Without the script, on a narrow screen, or
   under prefers-reduced-motion, none of these rules apply and the panels are
   ordinary stacked sections. The few rules outside that scope are the ones
   the stacked page needs so a rail-only element never shows twice. */

.dag-rail { position: relative; }

.dag-rail-viewport {
  position: relative;
  overflow: visible;
}

.is-railed .dag-rail-viewport {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  overflow: hidden;
  display: flex;
  align-items: center;
}

.is-railed .dag-rail-track {
  display: flex;
  align-items: stretch;
  height: 100%;
  will-change: transform;
  /* no transition: the transform IS the scroll position, and easing it would
     make the page lag behind the reader's own finger */
}

.is-railed [data-dag-panel] {
  flex: 0 0 100vw;
  max-width: 100vw;
  height: 100%;
  /* NOT a scroll container by default. A panel that captured the wheel would
     swallow it — `overscroll-behavior: contain` here stopped the scroll from
     chaining to the document, so the wheel over a panel moved nothing at all
     and the rail never advanced. Panels that genuinely overflow opt in below,
     and even those chain to the page at their limits. */
  overflow: hidden;
  padding: clamp(3.6rem, 7vh, 5.4rem) clamp(1.2rem, 4vw, 4rem) clamp(2rem, 4vh, 3rem);
  display: flex;
  flex-direction: column;
  justify-content: center;
  /* the frame's footage is absolutely positioned against the panel, so the
     panel is the containing block whatever else the stacked page decided */
  position: relative;
  isolation: isolate;
  opacity: 0.34;
  transform: scale(0.975);
  transition: opacity 0.5s ease, transform 0.5s ease;
}

.is-railed [data-dag-panel].is-current {
  opacity: 1;
  transform: none;
}

/* Only the panel in focus may scroll its own overflow, and it still chains
   to the page at the ends, so the rail always keeps moving. */
.is-railed [data-dag-panel].is-current.has-overflow {
  overflow-y: auto;
  overscroll-behavior-y: auto;
}

/* the braid: a DAG-ish lane under the track that fills as you travel */
.dag-rail-progress {
  display: none;
}

.is-railed .dag-rail-progress {
  display: block;
  position: sticky;
  bottom: 0;
  z-index: 4;
  height: 0;
}

.dag-rail-marks {
  position: absolute;
  bottom: clamp(1rem, 3vh, 2.2rem);
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.5rem 0.9rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--glass);
  backdrop-filter: blur(8px);
}

.dag-rail-marks > * {
  appearance: none; border: 0; padding: 0; cursor: pointer;
  width: 26px;
  height: 4px;
  border-radius: 999px;
  background: rgba(160, 244, 229, 0.24);
  transition: background 0.4s ease, width 0.4s ease;
}

.dag-rail-marks > .is-past { background: var(--teal-deep); }

.dag-rail-marks > .is-current {
  width: 46px;
  background: linear-gradient(90deg, var(--teal-deep), var(--mint));
  box-shadow: 0 0 16px var(--teal-glow);
}

/* the hint, shown once at the head of the rail */
.dag-rail-hint {
  position: absolute;
  bottom: clamp(1rem, 3vh, 2.2rem);
  right: clamp(1.2rem, 4vw, 3rem);
  font-family: var(--mono, monospace);
  font-size: 0.68rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--faint);
  display: none;
}

.is-railed .dag-rail-hint { display: block; }

/* A panel is one screen, so the sections inside one give up the vertical
   rhythm they use when stacked: the same content, tightened until it fits a
   viewport instead of asking the reader to scroll inside a panel that is
   already the whole screen. */
.is-railed [data-dag-panel] > .token-section-heading { margin-bottom: clamp(1rem, 2.4vh, 1.8rem); }
.is-railed [data-dag-panel] h2 { margin-bottom: 0.4rem; }
.is-railed [data-dag-panel] .token-heading-copy > p { margin-bottom: 0; }
.is-railed [data-dag-panel] > * + * { margin-top: clamp(0.8rem, 1.8vh, 1.4rem); }
.is-railed [data-dag-panel] .token-eyebrow { margin-bottom: 0.5rem; }

/* the rail's own chrome must not sit under the sticky nav */
.is-railed [data-dag-panel] { scroll-padding-top: 5rem; }

/* ── RAIL TYPOGRAPHY ──────────────────────────────────────────────────────
   The page's display sizes are built for a document that scrolls: an 83px
   heading with a 0.92 line-height reads as one confident line when there is
   room beneath it. Inside a panel there is no beneath — the panel IS the
   screen — so the same heading wraps, its lines collide, and the section
   spills past the fold. Rail mode gets its own scale, bounded by the SHORTER
   axis, because height is the constraint here and width never was. */
.is-railed [data-dag-panel] h2 {
  font-size: clamp(2.1rem, min(3.6vw, 5.6vh), 3.8rem);
  line-height: 1.08;
  letter-spacing: -0.015em;
  margin-bottom: 0.5rem;
}

.is-railed [data-dag-panel] .token-heading-copy > p,
.is-railed [data-dag-panel] .token-section-heading p {
  font-size: clamp(0.95rem, min(1.25vw, 2.2vh), 1.15rem);
  line-height: 1.6;
  max-width: 66ch;
}

.is-railed [data-dag-panel] .token-eyebrow {
  font-size: clamp(0.62rem, 1.4vh, 0.72rem);
  margin-bottom: 0.4rem;
}

/* the data furniture shrinks with it, so a panel is one screen of content
   rather than one screen plus a remainder */
.is-railed [data-dag-panel] .tiles,
.is-railed [data-dag-panel] .roadmap,
.is-railed [data-dag-panel] .cards,
.is-railed [data-dag-panel] .slots { gap: clamp(0.5rem, 1.4vh, 0.9rem); }

.is-railed [data-dag-panel] .tile,
.is-railed [data-dag-panel] .rm-col,
.is-railed [data-dag-panel] .card,
.is-railed [data-dag-panel] .slot,
.is-railed [data-dag-panel] .wall-card { padding: clamp(0.9rem, 2.2vh, 1.4rem) clamp(1rem, 1.5vw, 1.5rem); }

.is-railed [data-dag-panel] .rm-list li,
.is-railed [data-dag-panel] .slot-desc { font-size: clamp(0.86rem, 1.85vh, 1.02rem); line-height: 1.5; }

.is-railed [data-dag-panel] .rm-list { gap: clamp(0.25rem, 0.7vh, 0.5rem); }

/* NO PANEL SCROLLS ITS OWN CONTENT. The safety valve that let a too-tall
   panel scroll internally is exactly what made the wheel travel DOWN a
   little before the rail resumed travelling RIGHT — two directions from one
   gesture, which reads as broken. Content is sized to fit instead, and the
   wheel now only ever moves the rail. */
.is-railed [data-dag-panel].is-current.has-overflow { overflow: hidden; }

/* ── PANEL CHROME ─────────────────────────────────────────────────────────
   1. The sticky nav is ~69px tall and the panel's top padding was 63px, so
      every panel heading was sliced by the bar above it. The bottom
      reserves the band the marks and the hint sit in, so a panel's last
      row is never under the rail's own chrome. */
.is-railed [data-dag-panel] {
  padding-top: clamp(5.5rem, 11vh, 7.5rem);
  padding-bottom: clamp(3.6rem, 7vh, 4.8rem);
}

/* the heading's eyebrow column: wide enough that a three-word eyebrow is
   one line, and the gap to the copy a step tighter than the stacked page */
.is-railed [data-dag-panel] .token-section-heading {
  grid-template-columns: minmax(260px, 0.6fr) minmax(0, 1.4fr);
  gap: clamp(1.5rem, 3vw, 3rem);
}

/* 2. A neighbour panel is a viewport away, so it is only ever visible while
      the rail is between stops. Dimmed hard enough that a passing heading
      reads as motion rather than as two pages fighting. */
.is-railed [data-dag-panel] {
  opacity: 0.12;
  transition: opacity 0.45s ease, transform 0.45s ease;
}

.is-railed [data-dag-panel].is-current { opacity: 1; }

/* 3. The snap stops themselves: one per panel, invisible, at the scroll
      position where that panel comes to rest. The hero is a stop too, so a
      reader nudged back up lands on the title, not half a title. */
[data-dag-stops] { position: absolute; inset: 0; pointer-events: none; }
[data-dag-stops] i { position: absolute; left: 0; width: 1px; height: 1px; scroll-snap-align: start; }
/* proximity, never mandatory: a reader scrolling past the rail to the terms
   below must not be held hostage by it */
html.dag-snapping { scroll-snap-type: y proximity; }
html.dag-snapping .token-hero { scroll-snap-align: start; }

/* Two panels carry a list long enough that the intro paragraph above it is
   the thing pushing the last row off the screen. On a panel the heading has
   already said it — the prose returns in the stacked layout, where there is
   room for both. */
.is-railed [data-dag-panel="utility"] .token-heading-copy > p,
.is-railed [data-dag-panel="roadmap"] .token-heading-copy > p,
.is-railed [data-dag-panel="roadmap"] .rm-note { display: none; }

/* ── SHARED BY BOTH LAYOUTS ───────────────────────────────────────────────
   Rail-only lines and fail-closed figures: the stacked page must never show
   a "3 earlier" line above the three it lists, and no frame may show a unit
   under a number that has not arrived. */

/* the shipped column's tail line exists for the rail's cap; the stacked
   page lists every line, so the tail would count nothing there */
.token-page .rm-earlier { display: none; }

/* a lead whose figure is still empty hides its unit with it — visibility,
   not display, so the frame's layout never jumps when the number lands */
.token-page .frame-lead:has(> span:empty) { visibility: hidden; }

/* the doctrine strip: four rules under the roadmap, titled in the same
   mono the rest of the page uses for its labels */
.token-page .doctrine { margin-top: clamp(1.4rem, 3vw, 2.4rem); }
.token-page .doctrine-title {
  margin: 0 0 0.55rem;
  font: 500 0.68rem/1.5 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--faint);
}
.token-page .doctrine-title a { color: var(--teal); }

/* the split proportions, per frame: copy beside tiles, a console, a still
   or a wall. Set on the panel so both layouts share them (the stacked page
   collapses every split to one column under 900px in token-landing.css). */
.token-page [data-dag-panel="numbers"] { --frame-split: minmax(0, 0.46fr) minmax(0, 0.54fr); }
.token-page [data-dag-panel="treasury"] { --frame-split: minmax(0, 0.36fr) minmax(0, 0.64fr); }
.token-page [data-dag-panel="wall"] { --frame-split: minmax(0, 0.4fr) minmax(0, 0.6fr); }

/* ── THE FRAMES ───────────────────────────────────────────────────────────
   Six panels, each one trailer shot behind one headline and one number. The
   footage is a layer, never a row: it takes no height from the fit budget.
   At 1512×900 the content box is ≈738px tall (99px under the nav, 63px
   reserved for the marks) and the fit floor of 0.94 allows ≈785px; every
   rule below exists to land inside that at zoom 1. */

/* the footage is the first child, so the rhythm rule above would hand its
   margin to the copy: the layer has no height, the copy needs no gap */
.is-railed [data-dag-panel] > .frame-media + * { margin-top: 0; }

/* the one proof number, at panel scale */
.is-railed [data-dag-panel] .frame-lead {
  font-size: clamp(2.4rem, 6.4vh, 3.6rem);
  margin-bottom: clamp(0.3rem, 0.8vh, 0.5rem);
}

.is-railed [data-dag-panel] .frame-split {
  gap: clamp(1.2rem, 2.8vw, 2.8rem);
  align-items: center;
}

/* the copy column's prose, one step tighter than the stacked page */
.is-railed [data-dag-panel] .frame-copy > p,
.is-railed [data-dag-panel] .token-treasury-copy > p {
  margin: 0.6rem 0 0;
  font-size: clamp(0.88rem, 1.9vh, 1rem);
  line-height: 1.55;
  max-width: 60ch;
}

/* 1 · PROOF: copy and the curve's line on the left, six tiles in two
   columns on the right, the covenant id as one footer row */
.is-railed [data-dag-panel="numbers"] .tiles {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(0.45rem, 1.1vh, 0.7rem);
}
.is-railed [data-dag-panel="numbers"] .tile { min-height: 0; padding: clamp(0.65rem, 1.6vh, 0.9rem) 0.95rem; }
.is-railed [data-dag-panel="numbers"] .tile-n { margin-top: clamp(0.4rem, 1.1vh, 0.7rem); font-size: clamp(1.25rem, 3vh, 1.8rem); }
.is-railed [data-dag-panel="numbers"] .tile-sub { margin-top: 0.3rem; font-size: 0.66rem; line-height: 1.4; }
.is-railed [data-dag-panel="numbers"] .tile-prove { margin-top: 0.45rem; }
.is-railed [data-dag-panel="numbers"] .caveat { margin-top: 0.55rem; font-size: 0.74rem; line-height: 1.45; }
.is-railed [data-dag-panel="numbers"] .token-progress-card { margin-top: 0.8rem; padding: 0.7rem 0.9rem; }
.is-railed [data-dag-panel="numbers"] .gradbar { height: 6px; margin-bottom: 0.5rem; }
.is-railed [data-dag-panel="numbers"] .freshness { margin-top: 0.5rem; font-size: 0.66rem; }
.is-railed [data-dag-panel="numbers"] .frame-foot {
  width: auto;
  margin: 0;
  padding: 0.55rem 0.9rem;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--glass);
}

/* 2 · MONEY: the story at 0.36, the console at 0.64 — its readout at the
   panel scale it had when it owned a screen of its own */
.is-railed [data-dag-panel="treasury"] .token-treasury-live { margin-top: 0; }
.is-railed [data-dag-panel="treasury"] .tt-allocation-copy strong { font-size: clamp(2rem, 5.4vh, 3.2rem); }
.is-railed [data-dag-panel="treasury"] .tt-metrics article strong { font-size: clamp(1.2rem, 3vh, 1.7rem); }
.is-railed [data-dag-panel="treasury"] .tt-metrics { gap: clamp(0.5rem, 1.4vh, 1rem); }
.is-railed [data-dag-panel="treasury"] .tt-spark { height: clamp(24px, 4.5vh, 40px); }

/* 3 · MACHINE: the vault dial framed beside the heading, the three
   steps under both */
.is-railed [data-dag-panel="loop"] .loop-steps li { min-height: 0; }
.is-railed [data-dag-panel="loop"] .steps li {
  padding: clamp(0.85rem, 2vh, 1.2rem) 1.1rem;
  font-size: clamp(0.82rem, 1.75vh, 0.92rem);
  line-height: 1.5;
}
.is-railed [data-dag-panel="loop"] .loop-state { margin-top: 0.6rem; font-size: 0.8rem; }

/* 4 · PROMISES: the shipped column shows its newest five and counts the
   rest into the changelog; the four rules sit under the columns as a strip */
.is-railed [data-dag-panel="roadmap"] .rm-shipped .rm-list > li:nth-child(n + 6) { display: none; }
.is-railed [data-dag-panel="roadmap"] .rm-shipped .rm-list > li.rm-earlier { display: block; }
.is-railed [data-dag-panel="roadmap"] .rm-col { padding: clamp(0.8rem, 1.8vh, 1.1rem) 1.1rem; }
.is-railed [data-dag-panel="roadmap"] .rm-col::before { margin-bottom: 0.7rem; }
.is-railed [data-dag-panel="roadmap"] .rm-col h3 { min-height: 0; margin-bottom: 0.55rem; font-size: 0.95rem; }
.is-railed [data-dag-panel="roadmap"] .rm-list li { font-size: clamp(0.78rem, 1.7vh, 0.88rem); line-height: 1.45; }
.is-railed [data-dag-panel="roadmap"] .doctrine { margin-top: clamp(0.7rem, 1.6vh, 1.1rem); }
.is-railed [data-dag-panel="roadmap"] .cards {
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1px;
  border-radius: 14px;
}
.is-railed [data-dag-panel="roadmap"] .card { min-height: 0; padding: 0.65rem 0.85rem; }
.is-railed [data-dag-panel="roadmap"] .card h3 { margin: 0 0 0.25rem; font-size: 0.84rem; }
.is-railed [data-dag-panel="roadmap"] .card h3::before { display: inline-block; margin: 0 0.5rem 0 0; }
.is-railed [data-dag-panel="roadmap"] .card p { font-size: 0.74rem; line-height: 1.42; }

/* 5 · DOORS: every slot in one 5×2 grid, in the file's order, over the
   neon doorways; the capacity brackets as three tiles beneath */
.is-railed [data-dag-panel="utility"] .slots {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 0.55rem 0.6rem;
  align-content: start;
}
/* the stacked page lets the first two slots span two columns; five across
   has no room for a wide one */
.is-railed [data-dag-panel="utility"] .slots > .slot { grid-column: auto; margin: 0; min-height: 0; padding: 0.55rem 0.75rem; }
.is-railed [data-dag-panel="utility"] .slot-name { max-width: calc(100% - 4.4rem); font-size: 0.98rem; }
.is-railed [data-dag-panel="utility"] .slot .chip { top: 0.55rem; right: 0.55rem; }
.is-railed [data-dag-panel="utility"] .slot-desc { margin-top: 0.35rem; font-size: 0.74rem; line-height: 1.4; }

/* the brackets on a panel: three tiles across, not three banner rows. The
   full-width rows with their explainer sentences belong to the stacked page
   and /lane; on a one-screen panel the three numbers ARE the story. */
.is-railed [data-dag-panel="utility"] .loop-brackets {
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.6rem;
  margin-top: 0.45rem;
}
.is-railed [data-dag-panel="utility"] .bracket-row {
  grid-template-columns: 1fr;
  gap: 0.15rem;
  text-align: center;
  padding: 0.45rem 0.5rem;
}
.is-railed [data-dag-panel="utility"] .bracket-n { font-size: 1.4rem; }
.is-railed [data-dag-panel="utility"] .bracket-tier { font-size: 0.66rem; }
.is-railed [data-dag-panel="utility"] .bracket-what { display: none; }
.is-railed [data-dag-panel="utility"] .bracket-row .chip { justify-self: center; }
.is-railed [data-dag-panel="utility"] .brackets-title { font-size: 0.68rem; margin-bottom: 0.1rem; }

/* 6 · PEOPLE: the trailer's wall of holder portraits runs full-bleed
   behind the frame (a layer, no height), the six doors in two columns
   under the copy, the wall three by three beside them */
.is-railed [data-dag-panel="wall"] .token-note { margin-top: 0.45rem; font-size: 0.74rem; }
.is-railed [data-dag-panel="wall"] .cult-doors {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.4rem;
  margin-top: 0.7rem;
}
.is-railed [data-dag-panel="wall"] .cult-doors a { padding: 0.4rem 0.65rem; gap: 0.1rem; }
.is-railed [data-dag-panel="wall"] .cult-doors span { font-size: 0.72rem; }
.is-railed [data-dag-panel="wall"] .wall-grid {
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.55rem;
}
.is-railed [data-dag-panel="wall"] .wall-card { min-height: 0; padding: 0.65rem 0.75rem; gap: 0.65rem; }
.is-railed [data-dag-panel="wall"] .wall-count { margin-bottom: 0.6rem; }
.is-railed [data-dag-panel="wall"] .wall-count strong { font-size: 1.6rem; }
