/* ==========================================================================
   The CryptoMadness Ecosystem
   Mobile-first. Every spacing value sits on the 4px grid.
   ========================================================================== */

:root {
  /* Surface */
  --bg:        #04070a;
  --bg-raised: #0b1116;
  --bg-tile:   #0e161c;
  --line:      rgba(255, 255, 255, 0.09);
  --line-hi:   rgba(255, 255, 255, 0.18);

  /* Type. Both text colours clear WCAG AA on --bg. */
  --text:      #e9f1ed;   /* ~16.8:1 */
  --text-dim:  #9db0a8;   /*  ~8.1:1 */
  --text-mute: #6f817a;   /*  ~4.6:1, large text and non-essential only */

  --emerald:   #00ff88;
  --emerald-d: #00c76a;

  /* 4px grid */
  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px;
  --s6: 24px; --s8: 32px; --s12: 48px; --s16: 64px; --s20: 80px;

  --radius:    16px;
  --radius-sm: 10px;

  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto,
          "Helvetica Neue", Arial, sans-serif;
  --font-display: ui-serif, Georgia, "Iowan Old Style", "Times New Roman", serif;

  --ease: cubic-bezier(0.4, 0, 0.2, 1);
}

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

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* --------------------------------------------------------------- a11y --- */

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

.skip-link {
  position: absolute; left: var(--s4); top: var(--s4);
  transform: translateY(-200%);
  z-index: 100;
  padding: var(--s3) var(--s4);
  background: var(--emerald); color: #04070a;
  font-weight: 700; border-radius: var(--radius-sm);
  text-decoration: none;
  transition: transform 150ms var(--ease);
}
.skip-link:focus { transform: translateY(0); }

/* One focus treatment, applied everywhere. */
:where(a, button, [tabindex]):focus-visible {
  outline: 2px solid var(--emerald);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}

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

.site-header {
  position: sticky; top: 0; z-index: 50;
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s4);
  padding: var(--s3) var(--s4);
  background: rgba(4, 7, 10, 0.82);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--line);
}

.brand {
  display: inline-flex; align-items: center; gap: var(--s2);
  min-height: 44px;
  color: var(--text); text-decoration: none;
  font-weight: 650; letter-spacing: -0.01em;
}
.brand-mark {
  width: 26px; height: 26px;
  object-fit: contain;
  flex: none;
}
.brand-text { font-size: 15px; }

.site-header nav { display: flex; align-items: center; gap: var(--s1); }

.nav-link {
  display: none;
  padding: var(--s2) var(--s3);
  min-height: 44px; align-items: center;
  color: var(--text-dim); text-decoration: none;
  font-size: 14px; border-radius: var(--radius-sm);
  transition: color 150ms var(--ease), background 150ms var(--ease);
}
.nav-link:hover { color: var(--text); background: rgba(255, 255, 255, 0.05); }

.nav-cta {
  display: inline-flex; align-items: center;
  min-height: 44px; padding: var(--s2) var(--s4);
  background: var(--emerald); color: #04070a;
  font-size: 14px; font-weight: 700;
  border-radius: 999px; text-decoration: none;
  transition: transform 150ms var(--ease), box-shadow 150ms var(--ease);
}
.nav-cta:hover {
  transform: translateY(-1px);
  box-shadow: 0 6px 24px rgba(0, 255, 136, 0.28);
}
.nav-cta:active { transform: translateY(0); }

@media (min-width: 768px) {
  .site-header { padding: var(--s3) var(--s8); }
  .nav-link { display: inline-flex; }
  .brand-text { font-size: 16px; }
}

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

.hero { padding: var(--s12) var(--s4) var(--s8); }

.hero-intro {
  max-width: 40rem; margin: 0 auto var(--s12);
  text-align: center;
}

.eyebrow {
  margin: 0 0 var(--s3);
  font-size: 12px; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--emerald);
}

h1 {
  margin: 0 0 var(--s4);
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2.25rem, 8vw, 4.5rem);
  line-height: 1.05;
  letter-spacing: -0.02em;
}
.h1-line { display: block; }
.h1-accent { font-style: italic; color: var(--emerald); }

.lede {
  margin: 0 auto;
  max-width: 34rem;
  color: var(--text-dim);
  font-size: clamp(1rem, 2.4vw, 1.125rem);
}

/* -------------------------------------------------------------- stage --- */
/* Desktop: four platforms, mascot, four platforms, head follows the cursor.
   Mobile: the mascot STICKS to the top while the platforms scroll past it, and
   turns toward whichever tile you have scrolled to.

   It is a flex column here rather than a grid on purpose. A sticky grid item is
   confined to its own grid area, so the mascot would unstick the moment the
   first row scrolled off, which is exactly the bug this replaced: the owl left
   the screen immediately and the whole idea went with it. Flex gives a sticky
   item the whole container to travel in, and still honours `order`, which the
   mascot needs: it sits between the two columns in the markup so that the
   desktop grid reads left, mascot, right.                                   */

.stage {
  display: flex;
  flex-direction: column;
  max-width: 1280px;
  margin: 0 auto;
}

.column {
  list-style: none;
  margin: 0; padding: 0;
  display: grid; gap: var(--s3);
}
.column + .column { margin-top: var(--s3); }

.mascot {
  position: sticky;
  top: 52px;                       /* clears the sticky header */
  z-index: 5;
  order: -1;                       /* above both columns on mobile */
  display: flex; flex-direction: column;
  align-items: center; gap: var(--s3);
  padding-bottom: var(--s6);
  margin-bottom: var(--s2);

  /* Tiles scroll underneath, so the mascot needs its own ground. The gradient
     tail lets them slide out of view instead of being chopped off by a hard
     edge. */
  background: linear-gradient(to bottom,
              var(--bg) 0, var(--bg) 82%, rgba(4, 7, 10, 0) 100%);
}

.mascot-glow {
  position: absolute; inset: 8% 12%;
  background: radial-gradient(closest-side,
              rgba(0, 255, 136, 0.16), rgba(0, 255, 136, 0) 70%);
  filter: blur(18px);
  pointer-events: none;
}

.mascot-video,
.mascot-still {
  position: relative;
  width: 100%;
  max-width: min(200px, 42vw);
  height: auto;
  display: block;

  /* The clip's own background is not quite the page background: its corners sit
     near black but its edges carry the green rim glow, so the frame reads as a
     visible rectangle. Feathering just the outer band dissolves that edge while
     leaving the subject untouched. A radial mask would have clipped the
     shoulders, which run to the bottom and sides of frame. */
  -webkit-mask-image:
    linear-gradient(to right,  transparent 0, #000 9%, #000 91%, transparent 100%),
    linear-gradient(to bottom, transparent 0, #000 7%, #000 93%, transparent 100%);
  mask-image:
    linear-gradient(to right,  transparent 0, #000 9%, #000 91%, transparent 100%),
    linear-gradient(to bottom, transparent 0, #000 7%, #000 93%, transparent 100%);
  -webkit-mask-composite: source-in;
  mask-composite: intersect;
}
.mascot-still[hidden] { display: none; }

.mascot-hint {
  margin: 0;
  font-size: 12px; letter-spacing: 0.06em;
  color: var(--text-mute);
  white-space: nowrap;
  transition: opacity 300ms var(--ease);
}
.mascot-hint[data-faded="true"] { opacity: 0; }

/* Default from the media query, then corrected by JS via [data-mode] once the
   input is actually wired. See attachInputs(). */
.hint-desktop { display: none; }
.hint-touch   { display: inline; }

@media (hover: hover) and (pointer: fine) {
  .hint-desktop { display: inline; }
  .hint-touch   { display: none; }
}

.mascot-hint[data-mode="pointer"] .hint-desktop { display: inline; }
.mascot-hint[data-mode="pointer"] .hint-touch   { display: none; }
.mascot-hint[data-mode="touch"]   .hint-desktop { display: none; }
.mascot-hint[data-mode="touch"]   .hint-touch   { display: inline; }

@media (min-width: 640px) {
  .column { grid-template-columns: 1fr 1fr; }
  .mascot-video, .mascot-still { max-width: 260px; }
}

@media (min-width: 1024px) {
  .hero { padding: var(--s16) var(--s8) var(--s12); }

  /* Back to three columns, and the mascot stops being sticky: with the tiles
     either side of it, everything is on screen at once and there is nothing to
     follow. */
  .stage {
    display: grid;
    grid-template-columns: 1fr minmax(300px, 380px) 1fr;
    align-items: center;
    gap: var(--s6);
  }
  .column { grid-template-columns: 1fr; gap: var(--s4); }
  .column + .column { margin-top: 0; }
  .mascot {
    position: static;
    order: 0;
    min-height: 460px;
    padding-bottom: 0; margin-bottom: 0;
    background: none;
  }
  .mascot-video, .mascot-still { max-width: 100%; }
}

@media (min-width: 1280px) {
  .stage { gap: var(--s12); }
}

/* ---------------------------------------------------------- hub badge --- */
/* The centre the eight orbit. Shaped as a pill rather than a card so it does
   not read as a ninth tile. */

.hub-badge {
  --tile-color: var(--emerald);
  display: flex; align-items: center; gap: var(--s3);
  min-height: 44px;
  padding: var(--s2) var(--s4) var(--s2) var(--s2);
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--bg-tile);
  color: inherit; text-decoration: none;
  max-width: 100%;
  transition: border-color 200ms var(--ease),
              background 200ms var(--ease),
              transform 200ms var(--ease),
              box-shadow 200ms var(--ease);
}

.hub-badge:hover,
.hub-badge:focus-visible {
  transform: translateY(-1px);
  border-color: color-mix(in srgb, var(--tile-color) 60%, transparent);
  background: var(--bg-raised);
  box-shadow: 0 8px 30px color-mix(in srgb, var(--tile-color) 20%, transparent);
}
.hub-badge:active { transform: translateY(0); }

.hub-badge-logo {
  flex: none;
  width: 36px; height: 36px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--line);
  overflow: hidden;
}
.hub-badge-logo img { width: 100%; height: 100%; object-fit: contain; padding: 4px; }
.hub-badge-logo .tile-mono { font-size: 14px; }

.hub-badge-text { display: flex; flex-direction: column; min-width: 0; line-height: 1.25; }

.hub-badge-name {
  font-size: 14px; font-weight: 650; letter-spacing: -0.01em;
}
.hub-badge-tag {
  font-size: 11.5px;
  letter-spacing: 0.02em;
  color: var(--tile-color);
  filter: brightness(1.15);
}

.hub-badge-arrow { flex: none; color: var(--text-mute); }
.hub-badge:hover .hub-badge-arrow { color: var(--tile-color); }

/* --------------------------------------------------------------- tile --- */

.tile {
  --tile-color: var(--emerald);
  position: relative;
  display: flex; align-items: flex-start; gap: var(--s3);
  min-height: 44px;
  padding: var(--s4);
  background: var(--bg-tile);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  color: inherit; text-decoration: none;
  transition: border-color 200ms var(--ease),
              background 200ms var(--ease),
              transform 200ms var(--ease),
              box-shadow 200ms var(--ease);
}

a.tile:hover,
a.tile:focus-visible {
  transform: translateY(-2px);
  border-color: color-mix(in srgb, var(--tile-color) 55%, transparent);
  background: var(--bg-raised);
  box-shadow: 0 8px 32px color-mix(in srgb, var(--tile-color) 18%, transparent);
}
a.tile:active { transform: translateY(0); }

.tile-logo {
  flex: none;
  width: 52px; height: 52px;
  display: grid; place-items: center;
  border-radius: var(--radius-sm);
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--line);
  overflow: hidden;
}
.tile-logo img { width: 100%; height: 100%; object-fit: contain; padding: 6px; }

.tile-mono {
  font-family: var(--font-display);
  font-size: 18px; font-weight: 600;
  color: var(--tile-color);
}

.tile-body { min-width: 0; }

.tile-name {
  margin: 0;
  font-size: 15px; font-weight: 650;
  letter-spacing: -0.01em;
  display: flex; align-items: center; gap: var(--s2);
}

.tile-dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--tile-color);
  box-shadow: 0 0 10px var(--tile-color);
  flex: none;
}

.tile-tagline {
  margin: 2px 0 0;
  font-size: 12.5px;
  color: var(--tile-color);
  filter: brightness(1.15);
}

.tile-blurb {
  margin: var(--s2) 0 0;
  font-size: 13px; line-height: 1.5;
  color: var(--text-dim);
}

/* The tile the mascot is currently looking at. Set by the scroll handler on
   touch devices, where there is no cursor to do the pointing. Without it the
   mascot turns but nothing on the page says what it turned toward. */
.tile[data-active="true"] {
  border-color: color-mix(in srgb, var(--tile-color) 60%, transparent);
  background: var(--bg-raised);
  box-shadow: 0 8px 32px color-mix(in srgb, var(--tile-color) 18%, transparent);
}
.tile[data-active="true"] .tile-dot {
  box-shadow: 0 0 14px var(--tile-color), 0 0 26px var(--tile-color);
}

/* Unconfirmed platforms. Rendered as placeholders, never as fake links. */
.tile[data-status="tbc"] {
  border-style: dashed;
  background: transparent;
}
.tile[data-status="tbc"] .tile-name { color: var(--text-dim); }
.tile[data-status="tbc"]::after {
  content: "To confirm";
  position: absolute; top: var(--s3); right: var(--s3);
  font-size: 10px; font-weight: 700;
  letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--text-mute);
}

/* Loading state for the clip, the one asset heavy enough to wait on. */
.mascot[data-loading="true"] .mascot-video,
.mascot[data-loading="true"] .mascot-still { opacity: 0.35; }

.mascot[data-loading="true"]::after {
  content: "";
  position: absolute; inset: 0;
  border-radius: var(--radius);
  background: linear-gradient(90deg,
              transparent 25%, rgba(0, 255, 136, 0.07) 37%, transparent 63%);
  background-size: 400% 100%;
  animation: shimmer 1.4s ease-in-out infinite;
  pointer-events: none;
}
@keyframes shimmer {
  from { background-position: 100% 0; }
  to   { background-position: 0 0; }
}

/* Data failed to load entirely. */
.load-error {
  grid-column: 1 / -1;
  padding: var(--s4);
  border: 1px solid var(--line-hi);
  border-radius: var(--radius);
  color: var(--text-dim);
  font-size: 14px;
}
.load-error strong { display: block; color: var(--text); margin-bottom: var(--s1); }

/* ---------------------------------------------------------------- hub --- */

.hub {
  padding: var(--s12) var(--s4) var(--s16);
  border-top: 1px solid var(--line);
  display: flex; flex-direction: column; gap: var(--s12);
}
.hub-inner { max-width: 42rem; margin: 0 auto; text-align: center; }

.hub h2 {
  margin: 0 0 var(--s4);
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.75rem, 5vw, 2.75rem);
  letter-spacing: -0.02em;
}

/* The lead sets it slightly larger than the paragraph that follows, so the two
   read as a statement and its explanation rather than as two equal blocks. */
.hub-lead {
  margin: 0 0 var(--s4);
  color: var(--text);
  font-size: clamp(1.05rem, 2.6vw, 1.2rem);
  line-height: 1.55;
}

.hub-blurb { margin: 0; color: var(--text-dim); }

/* -------------------------------------------------------------- cycle --- */

.cycle-inner { max-width: 60rem; margin: 0 auto; }

.cycle-title {
  margin: 0 0 var(--s6);
  text-align: center;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.25rem, 3.2vw, 1.6rem);
  letter-spacing: -0.01em;
  color: var(--text);
}

.cycle {
  list-style: none;
  margin: 0 0 var(--s6);
  padding: 0;
  counter-reset: step;
  display: grid;
  gap: var(--s3);
}

.cycle li {
  counter-increment: step;
  position: relative;
  padding: var(--s4) var(--s4) var(--s4) var(--s12);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-tile);
}

.cycle li::before {
  content: counter(step, decimal-leading-zero);
  position: absolute;
  left: var(--s4); top: var(--s4);
  font-size: 12px; font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.06em;
  color: var(--emerald);
}

/* The loop closes: the last step is what feeds the first. */
.cycle li:last-child {
  border-color: rgba(0, 255, 136, 0.28);
  background: linear-gradient(180deg,
              rgba(0, 255, 136, 0.06), rgba(0, 255, 136, 0.02));
}

.cycle-step {
  margin: 0;
  font-size: 15px; font-weight: 650;
  letter-spacing: -0.01em;
}

.cycle-detail {
  margin: var(--s1) 0 0;
  font-size: 13.5px; line-height: 1.5;
  color: var(--text-dim);
}

.cycle-note {
  max-width: 40rem;
  margin: 0 auto;
  text-align: center;
  font-size: 14px;
  color: var(--text-mute);
}

@media (min-width: 640px) {
  .cycle { grid-template-columns: repeat(2, 1fr); gap: var(--s4); }
}
@media (min-width: 1024px) {
  .cycle { grid-template-columns: repeat(3, 1fr); }
}

.hub-link {
  display: inline-flex; align-items: center; gap: var(--s2);
  min-height: 44px; padding: var(--s3) var(--s6);
  border: 1px solid var(--line-hi);
  border-radius: 999px;
  color: var(--text); text-decoration: none;
  font-weight: 600; font-size: 15px;
  transition: border-color 200ms var(--ease), background 200ms var(--ease);
}
.hub-link:hover {
  border-color: var(--emerald);
  background: rgba(0, 255, 136, 0.08);
}

@media (min-width: 768px) { .hub { padding: var(--s16) var(--s8) var(--s20); } }

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

.site-footer {
  padding: var(--s8) var(--s4) var(--s12);
  border-top: 1px solid var(--line);
  text-align: center;
}
.site-footer p { margin: 0 auto; max-width: 38rem; font-size: 13px; color: var(--text-dim); }
.footer-fine { margin-top: var(--s3); color: var(--text-mute); font-size: 12px; }

@media (min-width: 768px) { .site-footer { padding: var(--s8) var(--s8) var(--s16); } }

/* ----------------------------------------------------- reduced motion --- */
/* The scrub is switched off in JS as well. This removes the rest.         */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  a.tile:hover, a.tile:focus-visible { transform: none; }
  .nav-cta:hover { transform: none; }
}
