/* ============================================================
   RANKED BEDWARS - Website Design System (prototype)
   Frost / ice / platinum theme, sampled from the glassy silver
   "R" logo. Owns tokens, glass, buttons, badges, motion.
   Shared components - section agents build ON TOP of these.
   ============================================================ */

@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&family=Sora:wght@600;700;800&family=Space+Grotesk:wght@500;600;700&display=swap');

/* ---------- Tokens ---------- */
:root {
  /* frost / ice scale (sampled from the silver-white logo) */
  --ice-50:  #F4F8FE;
  --ice-100: #E6EFFA;
  --ice-200: #CFE0F1;
  --ice-300: #B4CCE4;   /* bright accent (icons / links) */
  --ice-400: #97B4D6;   /* primary-light */
  --ice-500: #7E9CC4;   /* primary */
  --ice-600: #6480A6;
  --ice-700: #4E6488;

  --accent: var(--ice-300);
  --accent-strong: var(--ice-400);
  /* frosted-chrome sheen - white glass melting into steel-ice */
  --accent-grad: linear-gradient(135deg, #F1F7FF 0%, #CFE0F2 40%, #A9C2DE 72%, #86A6CC 100%);
  --accent-grad-soft: linear-gradient(135deg, rgba(207,224,242,.18), rgba(134,166,204,.10));

  /* ink / surfaces (cool near-black, faint blue undertone - white logo pops) */
  --bg-0: #070910;
  --bg-1: #0A0D15;
  --bg-2: #0F1320;
  --surface: rgba(255,255,255,0.032);
  --surface-2: rgba(255,255,255,0.055);
  --surface-3: rgba(255,255,255,0.085);
  --hairline: rgba(255,255,255,0.075);
  --hairline-strong: rgba(255,255,255,0.13);

  /* text */
  --text: #EAF1FA;
  --text-dim: #A4B4C8;
  --text-mute: #6A7A90;
  --text-faint: #47566a;

  /* status */
  --safe: #57D9A3;
  --moderate: #F5C451;
  --advanced: #FF8B6B;
  --danger: #FF6B7A;

  /* podium / medal accents (top-3 leaderboard, trophies) */
  --gold: #F3D08A;
  --silver: #CBD6E4;
  --bronze: #D8A57E;

  /* radii */
  --r-xs: 8px;
  --r-sm: 12px;
  --r-md: 16px;
  --r-lg: 22px;
  --r-xl: 30px;
  --r-pill: 999px;

  /* shadows / glow (cool white-blue frost) */
  --shadow-sm: 0 2px 8px rgba(0,0,0,.30);
  --shadow-md: 0 10px 30px -8px rgba(0,0,0,.58);
  --shadow-lg: 0 30px 70px -20px rgba(0,0,0,.72);
  --glow: 0 0 0 1px rgba(180,204,228,.35), 0 8px 40px -6px rgba(140,170,210,.44);
  --glow-soft: 0 0 34px -4px rgba(150,180,220,.30);

  /* motion */
  --e-out: cubic-bezier(.22,1,.36,1);
  --e-in-out: cubic-bezier(.65,0,.35,1);
  --e-spring: cubic-bezier(.34,1.56,.64,1);
  --t-fast: .16s;
  --t: .28s;
  --t-slow: .48s;

  /* layout */
  --maxw: 1180px;
  --side-w: 250px;     /* fixed left navigation rail (>= 1024px) */
  --topbar-h: 60px;    /* mobile bar that replaces the rail below 1024px */

  /* clean numerals for ELO / prices (Sora) */
  --font-price: 'Sora', 'Inter', system-ui, sans-serif;
}

/* ---------- Reset ----------
   Layered on purpose: the picking page runs Tailwind alongside this sheet,
   and an UNlayered universal reset outranks all of Tailwind's layered
   utilities (killing every margin/padding class). In @layer base it still
   beats browser defaults everywhere but loses to real declarations. */
@layer base {
  *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
}
/* Native, compositor driven. A JS wheel scroller used to live here and it made
   sticky panels swim; see the note above scrollToEl in site.js before changing this. */
html { scroll-behavior: smooth; }
/* Always reserve the scrollbar gutter. The cart drawer (.drawer-lock) and the checkout
   overlay (.vmodal-lock) both set overflow:hidden on html, which removes the scrollbar
   and lurches centred content sideways by half its width (measured: 7.5px on Windows
   Chrome's 15px classic scrollbars). Overlay-scrollbar platforms never showed it. */
html { scrollbar-gutter: stable; }
html, body { min-height: 100%; }
body {
  font-family: 'Inter', system-ui, 'Segoe UI', sans-serif;
  color: var(--text);
  background: var(--bg-0);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  letter-spacing: -0.01em;
  overflow-x: hidden;
  line-height: 1.5;
}
button, input, textarea, select { font-family: inherit; color: inherit; }
a { color: var(--accent); text-decoration: none; }
img { max-width: 100%; display: block; }
h1,h2,h3,h4 { font-weight: 800; letter-spacing: -0.03em; line-height: 1.08; }
::selection { background: rgba(180,204,228,.28); color: #fff; }

/* numeric / display font */
.display { font-family: 'Space Grotesk', 'Inter', sans-serif; letter-spacing: -0.02em; }
.grad-text { background: var(--accent-grad); -webkit-background-clip: text; background-clip: text; color: transparent; }
.tnum { font-family: var(--font-price); font-variant-numeric: tabular-nums lining-nums; }

/* ---------- Ambient background (fixed, behind everything) ---------- */
/* The page-transition veil paints itself with this same stack, so fading the veil
   in hides the content without touching the backdrop - see "Page transitions". */
/* The photo is a Bedwars screenshot, pre-blurred at build time (ffmpeg gblur)
   rather than with a CSS filter: a filtered fixed layer bleeds transparent at
   its edges and repaints on every scroll frame, and the transition veil below
   cannot reproduce a filter without blurring the content it is meant to hide.
   A baked-in blur keeps one asset that every surface can paint identically. */
:root {
  --bg-photo: url('../assets/site/bg.jpg') center / cover no-repeat;
  --bg-base-paint:
    radial-gradient(1100px 780px at 12% -8%, rgba(150,180,220,.10), transparent 60%),
    radial-gradient(900px 720px at 108% 40%, rgba(120,150,195,.07), transparent 58%),
    radial-gradient(700px 600px at 88% 90%, rgba(207,224,242,.05), transparent 60%),
    /* Flat, not a top-to-bottom fade. The layer is position:fixed, so a vertical
       gradient would pin its light end to the top of the VIEWPORT rather than to
       the top of the page: every section would pass through the bright band as it
       scrolled, and the glass surfaces (which lighten what is behind them) went
       pale enough there to drop dim text under 3:1. One flat value keeps contrast
       identical at every scroll position. */
    linear-gradient(rgba(7,9,16,.74), rgba(7,9,16,.74)),
    var(--bg-photo),
    linear-gradient(180deg, var(--bg-1), var(--bg-0));
}
.bg-layer { position: fixed; inset: 0; z-index: 0; pointer-events: none; }
.bg-base, .bg-photo { background: var(--bg-base-paint); }
/* The grain sits on top of the photo at 4%. It used to also carry
   `mix-blend-mode: overlay`, which forces the compositor to re-blend the entire
   stack beneath a full screen fixed layer on every frame. Over a flat near-black
   page that bought a little texture; over a photo it is not worth a per-frame
   full-viewport blend, so it is a plain overlay now.
   `.bg-mesh` used to sit here too: a third full screen fixed layer running a 22s
   animation under a 30px blur. The photo does that job now, so it is gone. */
.bg-grain {
  opacity: .05;
  background-image: 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='.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ---------- Page transitions (moving between rail entries) ----------
   A veil painted with the ambient backdrop, so a cross-page navigation dissolves
   the content while the background holds still. It lives on html::before rather
   than on body/main because animating opacity on those would re-parent every
   position:fixed child (the rail, bg layers, Discord bubble) mid-fade.
   Fading OUT on load is pure CSS so the veil is already covering at first paint;
   site.js only adds .pt-leave to fade it back IN before it navigates away.

   The veil starts where the content starts, not at the left edge. Covering the
   rail too meant the one element that is identical on every page blinked on every
   navigation, which is what made moving between tabs feel like a page reload
   rather than a view change. Now the rail and the background never move and only
   the content column dissolves. */
html::before {
  content: ''; position: fixed; inset: 0 0 0 var(--side-w); z-index: 9000; pointer-events: none;
  background: var(--bg-base-paint);
  background-attachment: fixed;   /* keep it aligned with .bg-base despite the inset */
  /* Resting state is CLEARED, and pageIn fills backwards rather than both, so the
     veil only ever hides the page while an animation is actively running. Parking
     the opaque state in a fill instead would mean any cancelled or unstarted
     animation leaves a full-screen veil with no way out - a blank site. */
  opacity: 0; visibility: hidden;
  animation: pageIn .34s var(--e-out) backwards;
}
@keyframes pageIn  { from { opacity: 1; visibility: visible; } to { opacity: 0; visibility: visible; } }
/* keep pageOut in step with PT_OUT in site.js */
html.pt-leave::before { animation: pageOut .15s var(--e-in-out) forwards; }
@keyframes pageOut { from { opacity: 0; visibility: visible; } to { opacity: 1; visibility: visible; } }
/* below 1024px the rail is a drawer, so there is nothing to spare on the left */
@media (max-width: 1023px) { html::before { inset: 0; } }

@media (prefers-reduced-motion: reduce) {
  html::before, html.pt-leave::before { animation: none; }   /* resting state above is already cleared */
}

/* ============================================================
   COMPONENTS (shared - agents reuse these)
   ============================================================ */

/* glass card */
.card {
  position: relative; background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--r-md); padding: 22px;
  backdrop-filter: blur(20px) saturate(120%); -webkit-backdrop-filter: blur(20px) saturate(120%);
  transition: transform var(--t) var(--e-out), border-color var(--t), box-shadow var(--t), background var(--t);
}
.card::before {
  content:''; position:absolute; inset:0; border-radius:inherit; pointer-events:none;
  background: linear-gradient(180deg, rgba(255,255,255,.06), transparent 40%);
  -webkit-mask: linear-gradient(#000,transparent 45%); mask: linear-gradient(#000,transparent 45%);
}
.card.hover:hover { transform: translateY(-3px); border-color: var(--hairline-strong); box-shadow: var(--shadow-md); background: var(--surface-2); }
.card.glow { box-shadow: var(--glow-soft); border-color: rgba(180,204,228,.3); }

/* buttons */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  border: 1px solid transparent; border-radius: var(--r-sm); cursor: pointer;
  font-size: 14px; font-weight: 600; padding: 12px 20px; white-space: nowrap;
  transition: transform var(--t-fast) var(--e-spring), box-shadow var(--t), background var(--t), border-color var(--t), opacity var(--t);
}
.btn svg { width: 17px; height: 17px; }
.btn:active { transform: scale(.97); }
.btn-primary { background: var(--accent-grad); color: #0a1320; box-shadow: 0 6px 22px -6px rgba(150,180,220,.6); }
.btn-primary:hover { box-shadow: 0 12px 38px -6px rgba(150,180,220,.9); transform: translateY(-2px); }
.btn-ghost { background: var(--surface-2); border-color: var(--hairline); color: var(--text); }
.btn-ghost:hover { background: var(--surface-3); border-color: var(--hairline-strong); }
.btn-outline { background: transparent; border-color: rgba(180,204,228,.4); color: var(--ice-200); }
.btn-outline:hover { background: var(--accent-grad-soft); border-color: rgba(180,204,228,.6); }
.btn-lg { padding: 15px 28px; font-size: 15.5px; border-radius: var(--r-md); }
.btn-block { width: 100%; }
.btn[disabled] { opacity: .4; pointer-events: none; }

/* badges / pills */
.badge { display: inline-flex; align-items: center; gap: 6px; font-size: 11px; font-weight: 700; letter-spacing: .03em; padding: 4px 11px; border-radius: var(--r-pill); text-transform: uppercase; }
.badge-safe { background: rgba(87,217,163,.14); color: var(--safe); }
.badge-moderate { background: rgba(245,196,81,.14); color: var(--moderate); }
.badge-advanced { background: rgba(255,139,107,.14); color: var(--advanced); }
.badge-pro { background: var(--accent-grad); color: #0a1320; }
.badge-new { background: rgba(180,204,228,.16); color: var(--ice-200); }
.badge-dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }

/* chip (glass pill w/ icon - trust markers) */
/* No backdrop-filter. A chip always sits on a panel that is already frosted, so
   its own blur was sampling an almost flat surface and buying nothing, while
   costing a compositor layer each. There are 13 of them on the home page alone,
   10 of those nested inside cards that are themselves blurring. A slightly more
   opaque fill reads the same. */
.chip {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 8px 15px; border-radius: var(--r-pill);
  background: var(--surface-2); border: 1px solid var(--hairline);
  font-size: 13px; font-weight: 600; color: var(--text-dim);
}
.chip svg { width: 15px; height: 15px; color: var(--accent); flex: 0 0 auto; }

/* eyebrow / kicker */
.eyebrow {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 12.5px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
  color: var(--accent);
}
/* An inline SVG with no width lays out at the 300x150 replaced-element default
   and crushes the kicker text into a narrow column of stacked words. Sections
   that size their own icon were fine; ones that did not were quietly broken.
   :where() makes this a zero-specificity default, so every existing rule and
   every future one still wins without needing !important. */
:where(.eyebrow) :where(svg) { width: 16px; height: 16px; flex: 0 0 auto; }

/* grid helpers */
.grid { display: grid; gap: 20px; }
.g-2 { grid-template-columns: repeat(2, 1fr); }
.g-3 { grid-template-columns: repeat(3, 1fr); }
.g-4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 940px) { .g-3, .g-4 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px) { .g-2, .g-3, .g-4 { grid-template-columns: 1fr; } }
.row { display: flex; align-items: center; gap: 12px; }
.wrap { flex-wrap: wrap; }
.center { text-align: center; }
.muted { color: var(--text-mute); }
.dim { color: var(--text-dim); }

/* motion keyframes reused across sections */
@keyframes fadeUp { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
@keyframes pop { from { opacity: 0; transform: scale(.9); } to { opacity: 1; transform: none; } }
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: .5; } }
@keyframes floatY { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-8px); } }
@keyframes shimmer { 0% { background-position: -400px 0; } 100% { background-position: 400px 0; } }
