/* =========================================================
   $CHIMPEPE — landing page
   Retro / cyberpunk. CRT construction from the terminal reference, recoloured:
   graphite shell, olive phosphor screen, amber + green neon.
   ========================================================= */

:root {
  --bg:        #07090a;
  --neon:      #00FF66;
  --neon-soft: #8CFF8C;
  --amber:     #FFB648;
  --gold:      #FFD029;
  --danger:    #FF2E4D;
  --text:      #D8F2E2;
  --muted:     #7d9c88;

  /* terminal */
  /* Graphite, not tan. The beige plastic came from the reference photo, but
     next to neon-on-black it was the one warm object on a cold page and read
     as a different site. Same CRT construction, colour that belongs. */
  --bezel-1:   #454d55;
  --bezel-2:   #2b3238;
  --bezel-3:   #161a1e;
  --screen-1:  #3b4a2f;
  --screen-2:  #222c1b;
  --screen-tx: #e8ecd8;

  --font-pix:  "Press Start 2P", ui-monospace, monospace;
  --font-term: "VT323", "Courier New", ui-monospace, monospace;

  /* Type scale.
     Press Start 2P is a bitmap-derived face: no hinting, no subpixel
     rendering to lean on, and a very wide advance. A size that looks fine
     as a label in a mockup is genuinely hard to read on a real screen, and
     the page had drifted down to 7-9px almost everywhere. Every step below
     is one notch up from where it was. Change these, not the rules. */
  --fs-xxs:   9px;    /* was 7  — copyright, address stubs */
  --fs-xs:   10px;    /* was 8  — disclaimer, chips, meta */
  --fs-sm:   11px;    /* was 9  — nav links, sub-headings, steps */
  --fs-md:   13px;    /* was 11 — modal title */
  --fs-lg:   15px;    /* was 13 — launcher names */
  --fs-title: 22px;   /* was 19 — section titles */
  --fs-term:  21px;   /* was 19 — VT323, the terminal's own text */

  --max: 1080px;

  /* 0.9 = the requested 10% reduction, applied to every badge dimension. */
  --badge-scale: 0.9;
  /* The brand mark is position:fixed in the bottom-right, so it hangs over
     whatever happens to be in that corner of the viewport at any scroll
     position. While the page was one 47vw column on the left that never
     mattered. Now that the sections below the fold run to the right edge it
     does: the last two buy steps were being clipped mid-word.
     So the corner is reserved. --badge-max caps the mark (its tagline wraps
     to two lines instead of running 320px wide), and --badge-reserve is that
     plus a gap, which .stage-wide and .footer subtract from their width. */
  --badge-max: 224px;
  --badge-reserve: 248px;          /* mark + a 24px gap */
  /* .stage already carries 20px of right padding, so its child subtracts that
     much less. Both land on the same right edge.

     These are margins, not `calc(100vw - …)`: 100vw includes the scrollbar
     but the elements are laid out inside a content box that excludes it, so
     the vw version quietly spent 15px of the gap and left 9px of clearance
     instead of 24. Margins are measured against the same box the element is
     in, so there is nothing to guess. */
  --badge-reserve-inner: 228px;
  /* --badge-w / --badge-h are gone: they existed only so the nav could
     reserve the top-right corner for the brand mark. The mark lives in the
     bottom-right now and the nav has the whole bar to itself. */
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  min-height: 100%;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-pix);
  font-size: var(--fs-lg);
  line-height: 1.9;
  -webkit-font-smoothing: none;
  overflow-x: hidden;
}

a { color: var(--neon); text-decoration: none; }
img { max-width: 100%; display: block; }

/* ================= VIDEO BACKGROUND ================= */

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

/* object-fit keeps the loop filling any viewport without distorting it. */
.bg-video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Darkened so white-on-video text stays legible at any frame of the loop. */
.bg-tint {
  position: absolute; inset: 0;
  /* Was heavy enough that the loop read as a dark texture rather than art.
     Lifted, with the weight kept on the left where the type sits. */
  background:
    linear-gradient(100deg, rgba(4,7,6,0.92) 0%, rgba(4,7,6,0.72) 42%, rgba(4,7,6,0.34) 100%),
    linear-gradient(180deg, rgba(4,7,6,0.55) 0%, rgba(4,7,6,0.10) 30%, rgba(4,7,6,0.80) 100%);
}

.bg-scan {
  position: absolute; inset: 0;
  background: repeating-linear-gradient(to bottom,
    rgba(0,255,102,0.035) 0 1px, transparent 1px 3px);
}

/* ================= BUTTONS ================= */

.btn {
  display: inline-block;
  font-family: var(--font-pix);
  font-size: var(--fs-md);
  letter-spacing: 1px;
  /* Explicit, because .btn is used on both <button> and <a>: the anchor was
     inheriting body's line-height of 1.9 and coming out 14px taller than the
     button sitting next to it. */
  line-height: 1.4;
  padding: 13px 18px;
  border-radius: 6px;
  border: 2px solid transparent;
  cursor: pointer;
  transition: transform 90ms ease, box-shadow 160ms ease, background 160ms ease;
}
/* Trimmed from 26px: side-by-side button pairs in a 47vw column were going
   a few pixels over and wrapping. */
.btn-lg { font-size: var(--fs-lg); padding: 16px 21px; }

/* Was a flat fill of --neon: the one untextured object on a page built out of
   bezels, noise and scanlines, and it read as pasted on. Same construction as
   the terminal's send key now — lit top edge, shaded bottom, a hard lip
   underneath it to sit on — so the primary call to action belongs to the
   arcade the rest of the page is made of. */
.btn-buy {
  color: #06210f;
  background: linear-gradient(180deg, #7dffb5 0%, var(--neon) 46%, #17c261 100%);
  border-color: #0a3a1d;
  box-shadow:
    inset 0 2px 0 rgba(255,255,255,0.55),
    inset 0 -4px 7px rgba(0,0,0,0.32),
    0 3px 0 #0a3a1d,
    0 0 20px rgba(0,255,102,0.45);
}
.btn-buy:hover {
  background: linear-gradient(180deg, #9dffc9 0%, #35ff85 46%, #1ad96e 100%);
  box-shadow:
    inset 0 2px 0 rgba(255,255,255,0.6),
    inset 0 -4px 7px rgba(0,0,0,0.28),
    0 3px 0 #0a3a1d,
    0 0 34px rgba(0,255,102,0.85);
}
.btn:active { transform: translateY(2px) scale(0.98); }

/* After .btn:active on purpose — same specificity, so source order decides.
   Travels the full height of its own lip, to read as pressed rather than
   nudged. scale() is gone: it blurred the pixel type at these sizes. */
.btn-buy:active {
  transform: translateY(3px);
  box-shadow:
    inset 0 3px 7px rgba(0,0,0,0.4),
    0 0 0 #0a3a1d,
    0 0 14px rgba(0,255,102,0.4);
}
.btn:focus-visible { outline: 2px dashed var(--gold); outline-offset: 4px; }

/* ================= NAV ================= */

.nav {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 14px;
  padding: 12px 18px;
  /* Transparent by request — at the top of the page, where it sits over the
     background loop and nothing else. */
  background: transparent;
  border-bottom: 0;
  transition: background 220ms ease, backdrop-filter 220ms ease,
              border-color 220ms ease;
  border-bottom: 1px solid transparent;
}

/* A text shadow was not enough. The bar is sticky, so once the page scrolls
   the links and the BUY button sit directly on top of body copy — "CHAT" and
   "ABOUT" were landing in the middle of a roadmap line and both became
   unreadable. So the transparency is kept where it was asked for (the top of
   the page) and a scrim fades in the moment anything is passing underneath.
   Toggled by site.js past 80px of scroll. */
.nav.is-stuck {
  background: linear-gradient(180deg, rgba(5,9,8,0.92) 0%, rgba(5,9,8,0.62) 70%, rgba(5,9,8,0) 100%);
  backdrop-filter: blur(9px);
  border-bottom-color: rgba(0,255,102,0.14);
}

.nav-menu { display: flex; align-items: center; gap: 18px; }
/* Padding, not height: these need a 44px touch target without changing
   the nav's visual rhythm. */
.nav-link {
  display: inline-flex; align-items: center;
  min-height: 44px; padding: 0 4px;
  font-size: var(--fs-sm); color: var(--text); opacity: 0.8;
}
.nav-link:hover { color: var(--neon); opacity: 1; }
/* The bar behind these is transparent now; without this they wash out
   wherever bright artwork scrolls under them. */
.nav-link, .nav-burger { text-shadow: 0 1px 3px rgba(0,0,0,0.9); }

.nav-socials { display: flex; align-items: center; gap: 10px; }
.social {
  display: grid; place-items: center;
  width: 44px; height: 44px;
  color: var(--text);
  border: 1px solid rgba(0,255,102,0.35);
  border-radius: 6px;
  background: rgba(0,0,0,0.3);
}
.social:hover { color: var(--neon); border-color: var(--neon); box-shadow: 0 0 12px rgba(0,255,102,0.35); }

.nav-burger {
  display: none;
  font-family: var(--font-pix);
  font-size: var(--fs-lg);
  color: var(--neon);
  background: transparent;
  border: 1px solid rgba(0,255,102,0.4);
  border-radius: 6px;
  padding: 8px 10px;
  min-width: 44px;                 /* it is the only nav control on a phone */
  min-height: 44px;
  cursor: pointer;
}

/* ================= BRAND MARK (bottom-right) ================= */

/* Every dimension below is a base value multiplied by --badge-scale, so the
   whole element -- logo, type and padding -- scales as one.

   It stays early in the DOM even though it renders at the bottom: it carries
   the page's only <h1>, and position:fixed puts it in the corner without
   pushing that heading to the end of the reading order. */
.brand-badge {
  position: fixed;
  top: 0;
  right: 0;
  z-index: 55;
  max-width: var(--badge-max);
  display: flex;
  flex-direction: column;          /* logo, then name, then tagline */
  align-items: center;
  text-align: center;
  gap: calc(9px * var(--badge-scale));
  padding: calc(16px * var(--badge-scale)) calc(20px * var(--badge-scale));
  /* No panel: the mark sits directly on the background loop. Everything that
     used to carry it — the gradient fill, the two hairline borders, the
     corner radius, the blur and the drop shadow — is gone by request. */
  background: none;
}

.badge-logo {
  width: calc(72px * var(--badge-scale));
  height: calc(72px * var(--badge-scale));
  flex: 0 0 auto;
  border-radius: 50%;                        /* the coin art is square; clip it round */
  border: 2px solid var(--neon);
  box-shadow: 0 0 22px rgba(0,255,102,0.5);
  animation: float 5s ease-in-out infinite;
}
@keyframes float { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-5px); } }

.badge-text {
  display: flex; flex-direction: column; align-items: center;
  gap: calc(6px * var(--badge-scale));
}

/* The neon and gold glows below are additive — they add light, so on their
   own they make bright artwork *harder* to read against, not easier. With the
   panel gone the mark sits straight on the loop, and the right of frame is its
   brightest region. So each glow is backed by a tight dark shadow, the same
   trick .nav-link uses for the same reason. Dark layers first, glow on top. */
.badge-name {
  margin: 0;                                 /* it is an <h1> now */
  font-size: calc(19px * var(--badge-scale));
  line-height: 1.2;
  color: var(--neon);
  text-shadow:
    0 1px 2px rgba(0,0,0,0.95),
    0 2px 6px rgba(0,0,0,0.85),
    0 0 12px var(--neon),
    0 0 30px rgba(0,255,102,0.45);
}
.badge-tagline {
  font-size: calc(10px * var(--badge-scale));
  letter-spacing: calc(1px * var(--badge-scale));
  line-height: 1.5;
  color: var(--gold);
  text-shadow:
    0 1px 2px rgba(0,0,0,0.95),
    0 2px 5px rgba(0,0,0,0.8),
    0 0 10px rgba(255,208,41,0.55);
}

.contract {
  display: inline-flex; align-items: center; gap: 10px;
  max-width: 100%;
  font-family: var(--font-pix);
  font-size: var(--fs-xs);
  color: var(--text);
  background: rgba(0,0,0,0.45);
  border: 1px solid rgba(0,255,102,0.4);
  border-radius: 6px;
  padding: 13px;
  min-height: 44px;
  cursor: pointer;
}
.contract:hover { border-color: var(--neon); }
.contract-tag { color: var(--muted); }
.contract-val { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.contract-copy { color: var(--neon); }

/* ================= LEFT COLUMN ================= */

/* The terminal and the launchers share one column pinned to the left. The
   right half is deliberately left open — the background loop has ChimPepe
   on that side, so filling it would cover the character. */
.stage {
  max-width: none;
  margin: 0;
  /* Left edge and column width come from the supplied mockup: the terminal
     sits 8.9% in from the left and spans 46.8% of the viewport. That is a
     proportion of the window, not a centred max-width box, so .stage drops
     the auto margins it used to have. Capped so the terminal does not become
     an absurd measure on an ultrawide display. */
  /* The badge is pinned top-right and this column is a 47vw strip on the
     left, so they never collide — the old badge-height clearance was pushing
     the terminal a fifth of the way down the page for nothing. */
  padding: 14px 20px 0 9vw;
}
.stage-left {
  /* 46.8% of the viewport, per the mockup's red rectangle. */
  width: min(46.8vw, 860px);
  display: flex;
  flex-direction: column;
}
/* sections inside either column drop their own outer padding */
.stage-left .section,
.stage-wide .section { max-width: none; margin: 0; padding: 0 0 12px; }

/* ---- below the fold ----
   The narrow column exists so the background character stays visible on the
   first screen. Past that screen the character is behind the fold and the
   right half was two thousand pixels of nothing, so this column is wider and
   lays out as a grid: ABOUT and ROADMAP span it, THE NUMBERS and HOW TO APE
   pair up. One break in the rhythm is enough — the page was six identical
   stacked blocks before this. */
.stage-wide {
  width: auto;
  max-width: 1080px;
  margin-right: var(--badge-reserve-inner);
  margin-top: 34px;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: 46px;
  row-gap: 30px;
  align-items: start;
}
.stage-wide #about   { grid-column: 1 / -1; }
.stage-wide #numbers { grid-column: 1; }
.stage-wide #buy     { grid-column: 2; }
.stage-wide #roadmap { grid-column: 1 / -1; }

/* The tint gradient is weighted left (0.92 -> 0.34), so a panel that reaches
   past ~60vw is sitting on a much brighter frame of the loop than anything in
   the narrow column. These two carry their own ground for that reason, not
   only for the structure it gives them. */
.panel {
  padding: 20px 22px 18px;
  border-radius: 12px;
  background: rgba(6,10,8,0.76);
  border: 1px solid rgba(0,255,102,0.22);
}
/* Colour finally doing structural work instead of decorating everything at
   one volume. Green is what you do; amber is what the thing is and is not.
   The palette already had --amber and --gold and barely used them. */
.panel-amber { border-color: rgba(255,182,72,0.32); }
.panel-amber .section-title { color: var(--amber); text-shadow: 0 0 12px rgba(255,182,72,0.45); }

/* Paired with HOW TO APE, THE NUMBERS gets ~384px of content width, and a
   190px label column left 182px for the value — "Fixed by odin.fun, not by
   us" wrapped to three lines against a one-line label. Stacked, both get the
   full measure and it reads as a spec sheet rather than a squeezed table. */
.stage-wide #numbers .fact { grid-template-columns: 1fr; gap: 2px; padding: 9px 0; }
.stage-wide #numbers .fact dt { opacity: 0.85; }

/* Three items in a row rather than three stacked bars, now there is width. */
.stage-wide .road { grid-template-columns: repeat(3, minmax(0, 1fr)); display: grid; }
.stage-wide .road-item { grid-template-columns: 1fr; gap: 6px; align-content: start; }

/* The yellow rectangles: inset 6.6% from the terminal's left edge, spanning
   90.9% of its width, with an 11.1% gap — so the pair reads as sitting under
   the terminal rather than being flush with it. */
.stage-left .launchers {
  grid-template-columns: repeat(2, 1fr);
  width: 90.9%;
  margin-left: 6.6%;
  gap: 11.1%;
}

/* ================= GHOST BUTTON ================= */
.btn-ghost {
  color: var(--neon);
  border-color: rgba(0,255,102,0.45);
  background: rgba(0,0,0,0.45);
}
.btn-ghost:hover { border-color: var(--neon); box-shadow: 0 0 20px rgba(0,255,102,0.3); }

/* ================= LEADERBOARD ================= */

.board {
  /* 22px was tuned against a launcher row 148px tall — the height it happens
     to be at 1280px wide. The row is not a fixed height: the descriptions
     rewrap with the column, so it runs 181px at 1025px wide and 131px from
     1440px up. A 50px swing that the single viewport-height constant on
     .chat-log cannot express, which is why a sliver of this board was showing
     above the fold on a 1920x1080 screen and the launchers were being clipped
     on a narrow one.
     So the constant below is tuned for the TALLEST row, and this gap is wider
     than the whole swing — the board then stays under the fold at every width
     while the launchers stay above it. It also reads better: the leaderboard
     is a different thing from the two launch buttons, and now looks like it.
     Dropped back down under the breakpoint, where the fold rule does not
     apply and 80px is just a hole. */
  margin-top: 80px;
  border: 1px solid rgba(0,255,102,0.25);
  border-radius: 12px;
  background: rgba(6,10,8,0.72);
  padding: 16px 18px 14px;
}

.board-head {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 10px;
  margin-bottom: 12px;
}
.board-title { margin: 0; font-size: var(--fs-md); color: var(--gold); letter-spacing: 1px; }

.board-tabs { display: flex; gap: 8px; }
.board-tab {
  font-family: var(--font-pix);
  font-size: var(--fs-xs);
  color: var(--muted);
  background: rgba(0,0,0,0.35);
  border: 1px solid rgba(0,255,102,0.22);
  border-radius: 5px;
  padding: 9px 12px;
  min-height: 44px;
  cursor: pointer;
}
.board-tab:hover { color: var(--text); border-color: rgba(0,255,102,0.5); }
.board-tab.is-on { color: #06210f; background: var(--neon); border-color: var(--neon); }
.board-tab:focus-visible { outline: 2px dashed var(--gold); outline-offset: 3px; }

.board-list { list-style: none; margin: 0; padding: 0; }

.board-row {
  display: grid;
  grid-template-columns: 30px 1fr auto;
  align-items: baseline;
  gap: 10px;
  padding: 7px 0;
  border-bottom: 1px solid rgba(0,255,102,0.09);
  font-family: var(--font-term);
  font-size: 19px;
  line-height: 1.25;
}
.board-row:last-child { border-bottom: 0; }
.board-rank { color: var(--muted); }
.board-row-1 .board-rank { color: var(--gold); }
.board-who { color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Same rule as the chat: the verified address rides with the name, so a
   display name can never stand in for an identity. */
.board-addr { color: #8fa878; opacity: 0.85; font-size: 0.8em; margin-left: 7px; }
.board-score { color: var(--neon); }
.board-row-me { background: rgba(0,255,102,0.06); }

.board-note { margin: 12px 0 0; font-family: var(--font-term); font-size: 17px; color: var(--muted); }
.board-warn {
  margin: 10px 0 0;
  font-family: var(--font-term);
  font-size: 16px;
  line-height: 1.35;
  color: var(--muted);
  opacity: 0.8;
  border-left: 2px solid rgba(255,182,72,0.45);
  padding-left: 10px;
}

/* ================= PROSE / FACTS / ROADMAP ================= */

.prose { max-width: 34em; }
.prose p {
  margin: 0 0 16px;
  font-family: var(--font-term);
  font-size: 21px;
  line-height: 1.38;
  color: var(--text);
}
.prose p:last-child { margin-bottom: 0; }
/* The honest paragraph. Marked because it is the one most sites bury. */
.prose-mark {
  border-left: 2px solid var(--neon);
  padding-left: 14px;
  color: var(--neon-soft) !important;
}

.facts { margin: 0 0 16px; padding: 0; }
.fact {
  display: grid;
  grid-template-columns: 190px 1fr;
  gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid rgba(0,255,102,0.10);
}
.fact:last-child { border-bottom: 0; }
.fact dt { font-family: var(--font-pix); font-size: var(--fs-xs); color: var(--muted); letter-spacing: 1px; }
.fact dd { margin: 0; font-family: var(--font-term); font-size: 20px; line-height: 1.3; color: var(--text); }

.facts-note {
  margin: 0;
  font-family: var(--font-term);
  font-size: 18px;
  color: var(--gold);
  opacity: 0.9;
}

.road { list-style: none; margin: 0 0 18px; padding: 0; display: grid; gap: 12px; }
.road-item {
  display: grid;
  grid-template-columns: 84px 1fr;
  gap: 14px;
  align-items: baseline;
  padding: 12px 14px;
  border: 1px solid rgba(0,255,102,0.18);
  border-radius: 9px;
  background: rgba(6,10,8,0.6);
}
.road-item.is-done { border-color: rgba(0,255,102,0.45); }
.road-when { font-family: var(--font-pix); font-size: var(--fs-xs); color: var(--gold); letter-spacing: 1px; }
.road-item.is-done .road-when { color: var(--neon); }
.road-what { font-family: var(--font-term); font-size: 20px; line-height: 1.3; color: var(--text); }

.road-note {
  margin: 0;
  font-family: var(--font-term);
  font-size: 18px;
  line-height: 1.35;
  color: var(--muted);
}

/* Visually gone, still announced by screen readers and still in the outline.
   Used where a heading would be redundant on screen but removing it outright
   would leave a section with no accessible name. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ================= SECTIONS ================= */

/* The nav is sticky, so a jump to #chat/#arcade/#buy would otherwise land
   with the section title hidden underneath it. */
/* One measure for the whole page: the buy section used to run to 1080px while
   everything above it stopped at the column width, so the page had two left
   edges and no consistent right one. */
.section { max-width: var(--max); margin: 0 auto; padding: 40px 20px; scroll-margin-top: 104px; }
/* Every section now sits inside .stage-left, so they all inherit one measure
   and one left edge — no per-section width overrides needed. */
.section-title {
  margin: 0 0 6px;
  font-size: var(--fs-title);
  color: var(--neon);
  text-shadow: 0 0 12px rgba(0,255,102,0.6);
}
/* Press Start 2P for names and labels; VT323 for anything you actually read.
   All-pixel-font was the single biggest reason the page felt fatiguing. */
.section-sub {
  margin: 0 0 9px;
  font-family: var(--font-term);
  font-size: 19px;
  letter-spacing: 0.5px;
  color: var(--muted);
}

/* ================= TERMINAL ================= */

.terminal {
  position: relative;
  max-width: 100%;
  margin: 0;
  padding: 14px 14px 12px;
  border-radius: 16px;
  /* weathered plastic bezel */
  background:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='3'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.35'/%3E%3C/svg%3E"),
    linear-gradient(160deg, var(--bezel-1) 0%, var(--bezel-2) 45%, var(--bezel-3) 100%);
  background-blend-mode: multiply, normal;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.14),
    inset 0 -3px 6px rgba(0,0,0,0.55),
    0 0 0 1px rgba(0,255,102,0.14),
    0 18px 40px rgba(0,0,0,0.65);
}

.terminal-screen {
  position: relative;
  border-radius: 9px;
  overflow: hidden;
  background: radial-gradient(ellipse at 50% 40%, var(--screen-1) 0%, var(--screen-2) 100%);
  box-shadow: inset 0 0 22px rgba(0,0,0,0.85), inset 0 0 60px rgba(0,0,0,0.5);
  border: 2px solid #0f1216;
}

/* CRT curvature + scanlines, above the text but click-through */
.screen-glass {
  position: absolute; inset: 0;
  pointer-events: none;
  z-index: 2;
  background:
    repeating-linear-gradient(to bottom, rgba(0,0,0,0.16) 0 1px, transparent 1px 3px),
    radial-gradient(ellipse at 50% 45%, transparent 55%, rgba(0,0,0,0.55) 100%);
}

.chat-log {
  list-style: none;
  margin: 0;
  padding: 14px 16px;
  /* Derived from the viewport, not fixed, so the first screen always ends
     exactly at the launchers — nothing below them peeks in, and no gap opens
     up on a tall monitor.
     521px is everything else in that first screen (nav, heading, terminal
     chrome, status line, and the launcher row at its TALLEST — 181px, which
     is what it measures around 1025px wide); 16px is breathing room under it.
     Measured, not guessed. It is a real dependency: it has already gone stale
     several times (dropping the arcade heading, dropping the chat subtitle,
     resizing the launcher art). Re-measure it whenever anything in that first
     screen changes height.

     Tuned for the tallest row on purpose. The row shrinks to 131px on a wide
     screen as the descriptions rewrap, which leaves up to 50px of extra slack
     under the launchers — absorbed by the 80px gap above .board, so nothing
     below ever creeps into the first screen. Tuning for the middle instead
     clipped the launchers at one end and showed the leaderboard at the other.

     Clamped so a very short window keeps a usable log and a very tall one
     does not turn the chat into a wall. */
  height: clamp(190px, calc(100vh - 537px), 620px);
  overflow-y: auto;
  font-family: var(--font-term);
  font-size: var(--fs-term);
  line-height: 1.42;
  color: var(--screen-tx);
  text-shadow: 0 0 6px rgba(200,255,180,0.35);
  scrollbar-width: thin;
  scrollbar-color: #6f7d5a transparent;
}
.chat-log::-webkit-scrollbar { width: 7px; }
.chat-log::-webkit-scrollbar-thumb { background: #6f7d5a; border-radius: 4px; }

.chat-line { word-wrap: break-word; overflow-wrap: anywhere; }
.chat-who { color: #cfe6a8; }
.chat-you { color: var(--amber); }
.chat-sys { color: #9fb98a; opacity: 0.75; }
/* The boot readout shown when the room is empty. Dimmer than a real message
   and spaced out, so 600px of phosphor with nobody in it reads as a machine
   idling rather than as a panel that failed to load. */
.chat-boot { color: #9fb98a; opacity: 0.55; letter-spacing: 0.5px; }
.chat-boot-ok { color: var(--neon); opacity: 0.75; }
/* The idle prompt. A terminal with a cursor on it is waiting; one without is
   broken, and at launch this panel is empty far more often than not. */
.chat-idle { color: #cfe6a8; opacity: 0.9; }
.chat-idle::after {
  content: '_';
  margin-left: 2px;
  animation: caret 1.05s steps(1) infinite;
}
@keyframes caret { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }
/* The signature-verified address, shown beside every name that has one.
   Dimmed so it reads as a credential rather than as part of the handle,
   but never hidden — it is the only thing that separates two people
   claiming the same name. */
.chat-addr { color: #8fa878; opacity: 0.85; font-size: 0.82em; }
/* Preview-mode lines. Deliberately loud: if this ever ships enabled, it must
   be obvious at a glance that nobody said any of it. */
.chat-sim { opacity: 0.72; }
.chat-simtag { color: var(--danger); letter-spacing: 1px; }
/* message bodies are inserted with textContent, never innerHTML */

/* sign-in row above the composer */
.terminal-auth {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 10px;
  min-height: 0;
}
.terminal-auth:empty { display: none; }

.auth-who {
  display: flex; align-items: baseline; gap: 7px;
  font-size: var(--fs-xs); color: var(--neon);
}
/* The verified address always renders next to the name, so a display name
   can never stand in for an identity. */
.auth-addr { font-size: var(--fs-xxs); color: var(--muted); opacity: 0.9; }

.auth-btn {
  font-family: var(--font-pix);
  font-size: var(--fs-xs);
  letter-spacing: 1px;
  color: var(--neon);
  background: rgba(0,0,0,0.35);
  border: 1px solid rgba(0,255,102,0.45);
  border-radius: 5px;
  padding: 11px;
  min-height: 44px;
  cursor: pointer;
}
.auth-btn:hover { border-color: var(--neon); box-shadow: 0 0 12px rgba(0,255,102,0.3); }
.auth-btn:disabled { opacity: 0.5; cursor: default; }
.auth-btn-primary { color: #06210f; background: var(--neon); border-color: var(--neon); }
.auth-btn-primary:hover { background: #6bffa8; }

.terminal-input:disabled { opacity: 0.65; cursor: not-allowed; }
.terminal-send:disabled { opacity: 0.5; cursor: not-allowed; }

.terminal-bar { display: flex; gap: 10px; margin-top: 12px; }

.terminal-input {
  flex: 1;
  min-width: 0;
  font-family: var(--font-term);
  font-size: var(--fs-term);
  color: var(--screen-tx);
  background: linear-gradient(180deg, #1c2419, #242e1e);
  border: 2px solid #0f1216;
  border-radius: 7px;
  padding: 7px 12px;
  box-shadow: inset 0 3px 8px rgba(0,0,0,0.6);
}
.terminal-input::placeholder { color: #7d8f6a; }
.terminal-input:focus { outline: none; border-color: rgba(0,255,102,0.5); }

.terminal-send {
  display: grid; place-items: center;
  width: 62px;
  min-height: 44px;
  color: #06210f;
  background: linear-gradient(180deg, #57e08d, #2fa862);
  border: 2px solid #0f1216;
  border-radius: 7px;
  cursor: pointer;
  box-shadow: inset 0 2px 0 rgba(255,255,255,0.45), 0 2px 4px rgba(0,0,0,0.4);
}
.terminal-send:hover { background: linear-gradient(180deg, #6bffa8, #3cc47a); }
.terminal-send:active { transform: translateY(2px); box-shadow: inset 0 2px 5px rgba(0,0,0,0.35); }

/* the little rubber feet from the reference */
.terminal-feet { display: flex; gap: 8px; padding: 8px 0 0 12px; }
.terminal-feet i { width: 7px; height: 7px; border-radius: 2px; background: rgba(0,0,0,0.55); }

.chat-note {
  margin: 8px 0 0;
  font-family: var(--font-term);
  font-size: 16px;
  color: var(--muted);
}

/* ================= GAME LAUNCHERS ================= */

.launchers {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 18px;
}

.launcher {
  display: grid;
  /* A balance: the cabinet art is portrait and wants room, but every pixel
     it takes comes out of the text column, and "BANANA HEIST" needs ~120px
     to stay on one line. 70/130 is the split that satisfies both. */
  grid-template-columns: 70px 1fr;
  grid-template-areas: "art meta" "go go";
  gap: 11px;
  align-items: center;
  text-align: left;
  font-family: var(--font-pix);
  padding: 13px 15px;
  border-radius: 16px;
  border: 2px solid currentColor;
  background: rgba(6,10,8,0.72);
  cursor: pointer;
  transition: transform 160ms ease, box-shadow 200ms ease, background 200ms ease;
}
.launcher-amber { color: var(--amber); box-shadow: 0 0 22px rgba(255,182,72,0.30), inset 0 0 26px rgba(255,182,72,0.10); }
.launcher-green { color: var(--neon-soft); box-shadow: 0 0 22px rgba(140,255,140,0.30), inset 0 0 26px rgba(140,255,140,0.10); }
.launcher:hover { transform: translateY(-4px); background: rgba(10,16,12,0.86); }
.launcher-amber:hover { box-shadow: 0 0 38px rgba(255,182,72,0.55), inset 0 0 30px rgba(255,182,72,0.16); }
.launcher-green:hover { box-shadow: 0 0 38px rgba(140,255,140,0.55), inset 0 0 30px rgba(140,255,140,0.16); }
.launcher:focus-visible { outline: 2px dashed var(--gold); outline-offset: 4px; }

.launcher-art { grid-area: art; display: grid; place-items: center; height: 78px; }

/* The arcade cabinets. They bring their own glow, so no drop-shadow here —
   stacking another one just muddies the neon. */
.cab { width: auto; height: 78px; }

.launcher-meta { grid-area: meta; display: flex; flex-direction: column; gap: 5px; min-width: 0; }
/* 15px broke "BANANA HEIST" across two lines once the boxes narrowed to the
   mockup's 19vw. 11px keeps every name on one line in the text column. */
.launcher-name { font-size: var(--fs-xs); line-height: 1.35; text-shadow: 0 0 10px currentColor; }
.launcher-desc {
  font-family: var(--font-term);
  font-size: 16px;
  line-height: 1.25;
  color: var(--text);
  opacity: 0.8;
}
.launcher-best { font-size: var(--fs-xxs); color: var(--gold); min-height: 11px; }

.launcher-go {
  grid-area: go;
  margin-top: 2px;
  font-size: var(--fs-xs);
  letter-spacing: 1px;
  text-align: right;
  opacity: 0.85;
}

/* ================= BUY ================= */

.steps { list-style: none; margin: 0 0 26px; padding: 0; display: grid; gap: 12px; }
.steps li {
  display: flex; gap: 13px; align-items: baseline;
  font-family: var(--font-term);
  font-size: 19px;
  line-height: 1.45;
}
.steps b {
  flex: 0 0 auto;
  display: grid; place-items: center;
  width: 27px; height: 27px;
  font-size: var(--fs-xs);
  color: #06210f;
  background: var(--neon);
  border-radius: 5px;
}

/* ================= FOOTER ================= */

/* Aligned to the column above it rather than centred on the viewport. It was
   `max-width: 1080px; margin: 0 auto`, which put its left edge at 173px while
   every other thing on the page started at 130px — two left edges and two
   alignments on one page, for no reason other than that the footer had been
   written before the column had. Same width and same 9vw origin as
   .stage-wide now, so the page has one spine from the terminal to the
   copyright line. */
.footer {
  width: auto;
  max-width: 1080px;
  margin: 0 var(--badge-reserve) 0 9vw;
  padding: 34px 0 46px;
  border-top: 1px solid rgba(0,255,102,0.18);
  text-align: left;
}
.footer-logo {
  width: 34px; height: 34px;
  margin: 0 0 14px;
  border-radius: 50%;
  border: 1px solid rgba(0,255,102,0.5);
  opacity: 0.85;
}
.disclaimer {
  max-width: 720px;
  margin: 0 0 14px;
  font-family: var(--font-term);
  font-size: 16px;
  line-height: 1.5;
  color: var(--muted);
}
.disclaimer b { color: var(--text); }
.copyright { margin: 0; font-size: var(--fs-xxs); color: var(--muted); opacity: 0.7; }

/* ================= GAME MODAL ================= */

.modal { position: fixed; inset: 0; z-index: 80; display: flex; flex-direction: column; background: rgba(3,6,5,0.97); }
.modal[hidden] { display: none; }

.modal-bar {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding: 11px 16px; border-bottom: 1px solid rgba(0,255,102,0.25);
}
.modal-title { font-size: var(--fs-md); color: var(--neon); }
.modal-actions { display: flex; align-items: center; gap: 14px; }
.modal-tab { font-size: var(--fs-xs); color: var(--muted); }
.modal-tab:hover { color: var(--neon); }
.modal-x {
  font-family: var(--font-pix); font-size: var(--fs-md); color: var(--neon);
  width: 44px; height: 44px; cursor: pointer;
  background: transparent; border: 1px solid rgba(0,255,102,0.4); border-radius: 5px;
}
.modal-x:hover { border-color: var(--neon); }
.modal-stage { flex: 1; min-height: 0; padding: 12px; }
.modal-stage iframe { width: 100%; height: 100%; border: 0; border-radius: 8px; display: block; }

/* ================= RESPONSIVE ================= */

/* Side-by-side nav and badge need room for both. Below this the badge
   becomes a full-width bar and the nav collapses into the burger — which is
   why the breakpoint tracks the badge's width rather than a phone size. */
@media (max-width: 1024px) {
  .nav { flex-wrap: wrap; }
  .nav-burger { display: block; }

  /* Burger left, BUY right, menu wrapping onto its own line underneath.
     `order` is what keeps the menu last — in DOM order it sits before the
     CTA, so without this it wraps first and pushes BUY to a third row. */
  .nav-buy { margin-left: auto; order: 1; }
  /* The brand mark moved into this corner, and `margin-left:auto` drives BUY
     straight under it. The mark is fixed at z-index 55 against the nav's 40,
     so the collision is not just visual — it swallows the tap and the primary
     CTA stops working. Reserving the mark's width (224px here) as nav padding
     stops every nav item short of it instead. */
  .nav { padding-right: 129px; }
  .nav-menu { order: 2; }

  .section { scroll-margin-top: 84px; }

  /* menu collapses into a stacked panel under the bar */
  .nav-menu {
    display: none;
    flex-basis: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: 12px;
    padding-top: 12px;
  }
  .nav-menu.open { display: flex; }
  .nav-socials { justify-content: center; }
  .nav-link { text-align: center; font-size: var(--fs-md); }
  .btn-buy { text-align: center; }

  /* Still a bottom-right corner mark, just smaller — at full size it would
     swallow a phone screen. The footer gets matching bottom padding so no
     content ends up permanently stuck behind it.

     --badge-scale now drives the BOX only (padding, gap, logo), never the
     type. Multiplying a 10px tagline by a scale factor is how it ended up
     rendering at 6.2px here and 4.05px on a phone — measured, not guessed.
     Type gets explicit sizes that stay readable at every breakpoint. */
  /* One compact mark for everything below the desktop breakpoint.
     At 0.62 the mark stood 125px tall against a 73px nav, so 52px of it hung
     BELOW the bar — and here the columns have collapsed to full width, so
     there is no reserved right edge to catch them. 35 elements scrolled under
     it, the chat lines and both launcher cards among them.
     At this size it fits inside the nav band (71px vs 73px), which is what
     the phone rules were already doing, so it occludes nothing the sticky nav
     was not already covering. The tagline goes for the same reason it goes on
     a phone: it survives in the page title, the link preview and the footer. */
  .brand-badge { --badge-scale: 0.45; gap: 5px; }
  .badge-logo { width: 38px; height: 38px; }
  .badge-name { font-size: 11px; }
  .badge-tagline { display: none; }
  /* The footer's bottom reservation is gone with the mark: it existed only to
     keep the copyright line out from under a bottom-right badge. */
  /* Below the breakpoint the column is full width, so the mockup's 9vw left
     edge and the launcher inset both stop applying. */
  .stage { padding: 22px 20px 0; }
  .stage-left { width: 100%; }
  /* One column again: at this width the pairing has nowhere to go. */
  /* The mark shrinks and the columns collapse, so the reserved corner goes. */
  .stage-wide { width: auto; max-width: none; margin-right: 0;
                grid-template-columns: 1fr; column-gap: 0; }
  .stage-wide #numbers, .stage-wide #buy { grid-column: 1 / -1; }
  .stage-wide .road { grid-template-columns: 1fr; }
  .panel { padding: 16px 16px 14px; }
  /* .stage drops its 9vw origin here, so the footer drops it too. */
  .footer { width: auto; max-width: none; margin: 0;
            padding-left: 20px; padding-right: 20px; }
  .stage-left .launchers { width: 100%; margin-left: 0; gap: 18px; }

  .chat-log { height: 280px; font-size: 19px; }
  .board { margin-top: 28px; }
  .launcher { grid-template-columns: 68px 1fr; }
  .fact { grid-template-columns: 1fr; gap: 3px; }
  .road-item { grid-template-columns: 1fr; gap: 5px; }
  .board-head { flex-direction: column; align-items: flex-start; }
  .stage-left .launchers { grid-template-columns: 1fr; }
}

@media (max-width: 520px) {
  body { font-size: var(--fs-md); }
  /* 0.62 still ate over half a 375px screen. A corner mark should read as a
     mark, and it is a link, so anything oversized also swallows taps there.

     The tagline goes rather than shrinks. At a size that fits a phone corner
     it was rendering at 4px — present in the DOM, legible to nobody, and
     still taking the width. It is already in the page title, the link
     preview and the footer, so a phone loses nothing by dropping it here.
     What is left is a logo and a name, both at sizes you can actually read. */
  /* The mark's phone treatment moved up to the 1024 breakpoint — it applies
     from there down, so there is nothing left to override here. */
  .section-title { font-size: 17px; }
  .btn-lg { font-size: var(--fs-md); padding: 14px 18px; }

  .terminal { padding: 10px 10px 8px; border-radius: 12px; }
  .chat-log { height: 240px; font-size: 18px; padding: 11px 12px; }
  .terminal-input { font-size: 18px; }
  .terminal-send { width: 52px; }
  .prose p { font-size: 19px; }
  .board-row { grid-template-columns: 26px 1fr auto; font-size: 17px; }
  .board-addr { display: block; margin-left: 0; }

  .launcher { grid-template-columns: 1fr; grid-template-areas: "art" "meta" "go"; text-align: center; }
  .launcher-meta { align-items: center; }
  .launcher-go { text-align: center; }
}

/* ================= TOKENOMICS READOUT ================= */

/* The tokenomics sit inside the chat terminal's own shell, so these rules only
   style the text ON the phosphor — the bezel, screen and scanline glass all
   come from .terminal / .terminal-screen / .screen-glass unchanged. Colours are
   the chat's, not the page's: --text on a green CRT reads as a paste-in. */
.readout { margin: 0; padding: 13px 15px; }
.readout-row {
  display: grid;
  grid-template-columns: 116px 1fr;
  gap: 12px;
  align-items: baseline;
  padding: 9px 0;
  border-bottom: 1px solid rgba(232,236,216,0.13);
}
.readout-row:last-child { border-bottom: 0; }
.readout dt {
  font-family: var(--font-pix);
  font-size: var(--fs-xs);
  letter-spacing: 1px;
  color: #9fb98a;
}
.readout dd {
  margin: 0;
  font-family: var(--font-term);
  font-size: 20px;
  line-height: 1.32;
  color: var(--screen-tx);
  /* the same phosphor bloom the chat log carries */
  text-shadow: 0 0 6px rgba(200,255,180,0.35);
}

/* ================= ROADMAP PHASES ================= */

/* .road-item is a 2-column grid (label | body); the body is now a title plus a
   sub-list, so it needs its own stacking context rather than a second bare
   span. */
.road-body { display: grid; gap: 7px; min-width: 0; }
.road-sub { list-style: none; margin: 1px 0 0; padding: 0; display: grid; gap: 5px; }
.road-sub li {
  position: relative;
  padding-left: 16px;
  font-family: var(--font-term);
  font-size: 18px;
  line-height: 1.35;
  color: var(--muted);
}
/* A terminal prompt rather than a bullet — the page already speaks this
   language in the chat's boot readout. Absolute, so it never becomes a grid
   item and never shifts the text. */
.road-sub li::before {
  content: '>';
  position: absolute;
  left: 0;
  top: 0;
  color: var(--neon);
  opacity: 0.65;
}

/* ================= SMALL FIXES ================= */

/* VT323 ships a 400 face only, so `bold` here is the browser faking it and
   smearing the pixel glyphs sideways. The section's own emphasis idiom is
   .disclaimer b: colour, never weight. */
#about .prose-mark strong { font-weight: normal; color: var(--neon); }

/* .contract is a <button>, so .btn:focus-visible never reached it and it was
   the one control on the page with no visible focus state. */
.contract:focus-visible { outline: 2px dashed var(--gold); outline-offset: 3px; }

/* The readout label column is 116px of pixel type; below this it eats the
   value's measure, so the pair stacks. */
@media (max-width: 620px) {
  .readout { padding: 11px 12px; }
  .readout-row { grid-template-columns: 1fr; gap: 3px; padding: 8px 0; }
  .readout dd { font-size: 19px; }
  .road-sub li { font-size: 17px; }
}

@media (prefers-reduced-motion: reduce) {
  .badge-logo { animation: none; }
  html { scroll-behavior: auto; }
}
