/* ══════════════════════════════════════════════════════════════════════════
   VantageMC — site styles

   THE SITE STARTS IN DAYLIGHT AND CLIMBS INTO SPACE.
   That is the whole organising idea and it is not decorative. The badge is a
   bright object — cream wordmark, white clouds, light blue — and it was sitting
   on a near-black page, which is why the site read as a different brand from
   its own logo. Skyblock is islands in a bright sky, not a void. So the page
   is daylight by default, and the dark is EARNED: it arrives only at the top
   of the rank ladder, where Celestial actually is deep space.

   THE PALETTE IS THE LOGO'S OWN. Every hue below was read out of
   web/assets/logo.svg rather than picked to taste, so the page and the badge
   cannot drift apart. If the logo is redrawn, re-read them:
     grep -oiE '#[0-9a-f]{6}' web/assets/logo.svg | sort | uniq -c | sort -rn

   docs/BRAND.md NOW MATCHES THIS FILE (fixed 2026-09-03; it had specified an
   aqua #5BE9FF -> violet #B47BFF pair that no shipped asset ever used). If the
   two drift again, THIS FILE WINS - it is read from the artefact that ships -
   and BRAND.md says so itself.
   ══════════════════════════════════════════════════════════════════════════ */

:root {
  /* ── Ink. The logo's own outline colour, used as type. ──────────────── */
  --ink:       #03122B;
  --ink-soft:  #33527D;
  --ink-faint: #6B87AE;

  /* ── Daylight grounds ───────────────────────────────────────────────── */
  --day:       #EAF3FB;   /* the sky the page sits in */
  --day-warm:  #FAF4EB;   /* the wordmark's cream — warm surfaces */
  --white:     #FFFFFF;   /* cloud */
  --line:      #CFE0F0;   /* hairlines on light */

  /* ── From the badge ─────────────────────────────────────────────────── */
  --sky:       #72B3E3;
  --sky-deep:  #3D7CB8;   /* links and hovers — passes contrast on light */
  --mint:      #65E2B6;
  --mint-deep: #1E9E77;   /* mint is too pale for text on light; this is not */
  --gold:      #F7BD46;
  --gold-deep: #A9761A;   /* same problem, same fix */

  /* ── Night. Earned, not default. ────────────────────────────────────── */
  --navy:      #0A1E3D;
  --navy-deep: #03122B;
  --navy-edge: #1E3A66;
  --cream:     #FAF4EB;   /* type on night */
  --haze:      #A9C0DC;   /* body on night */

  /* ── The rank ladder ───────────────────────────────────────────────────
     Four of five come from the badge art. NEBULA IS THE ONE EXTENSION: the
     logo has no purple, but five tiers need five identities and a nebula that
     is another blue is not a tier. Codex's badge art reached the same value
     independently, which is the check that matters. */
  --t-cloud:     #5C9BD1;
  --t-storm:     #3F62B0;
  --t-aurora:    #1E9E77;
  --t-nebula:    #7A5CC4;
  --t-celestial: #C08F22;

  /* ── Type ──────────────────────────────────────────────────────────────
     Baloo 2 is rounded and heavy, which is what the badge is. The face here
     before was Chakra Petch — squared, technical, drawn for instrument
     panels — and beside a cartoon cloud badge it read as two brands sharing
     a page. */
  --display: 'Baloo 2', ui-rounded, system-ui, sans-serif;
  --body: 'Nunito Sans', system-ui, -apple-system, sans-serif;
  --mono: 'JetBrains Mono', ui-monospace, Menlo, monospace;

  --gutter: clamp(1.25rem, 4vw, 3.5rem);
  --measure: 66ch;
  --shell: 1180px;
}

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; overflow-x: clip; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}

body {
  margin: 0;
  background: var(--day);
  color: var(--ink-soft);
  font-family: var(--body);
  font-size: clamp(1rem, .95rem + .22vw, 1.09rem);
  line-height: 1.68;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img { max-width: 100%; display: block; }

:focus-visible { outline: 3px solid var(--sky-deep); outline-offset: 3px; border-radius: 4px; }
:focus:not(:focus-visible) { outline: none; }

.skip {
  position: absolute; left: 0; top: 0; transform: translateY(-120%);
  background: var(--ink); color: var(--cream);
  padding: .75rem 1.15rem; z-index: 100;
  font: 700 .9rem/1 var(--display); text-decoration: none;
}
.skip:focus { transform: translateY(0); }

/* ─── Type ─────────────────────────────────────────────────────────────── */
h1, h2, h3, h4 {
  font-family: var(--display);
  color: var(--ink);
  line-height: 1.08;
  margin: 0;
  font-weight: 800;
  letter-spacing: -.005em;
}
h1 { font-size: clamp(2.7rem, 1.5rem + 5.2vw, 5rem); }
h2 { font-size: clamp(1.95rem, 1.4rem + 2.1vw, 2.85rem); }
h3 { font-size: clamp(1.2rem, 1.05rem + .7vw, 1.5rem); font-weight: 700; }

p { margin: 0 0 1.15em; max-width: var(--measure); }
p:last-child { margin-bottom: 0; }

a { color: var(--sky-deep); text-underline-offset: 3px; }
a:hover { color: var(--ink); }
strong { color: var(--ink); font-weight: 700; }
code { font-family: var(--mono); color: var(--ink); font-size: .92em; }

.eyebrow {
  display: block; margin-bottom: .9rem;
  font: 700 .74rem/1 var(--display);
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--gold-deep);
}

/* ─── Shell ────────────────────────────────────────────────────────────── */
.shell { width: 100%; max-width: var(--shell); margin-inline: auto; padding-inline: var(--gutter); }
section { padding-block: clamp(3.5rem, 7vw, 6rem); position: relative; }
.rule { border: 0; height: 1px; background: var(--line); margin: 0; }

/* Alternating grounds so the page has weather rather than one flat field. */
.band-warm { background: var(--day-warm); }
.band-white { background: var(--white); }

/* ─── NIGHT SECTIONS ─────────────────────────────────────────────────────
   Opt-in, not the default. Used for the footer and the top of the climb —
   the two places the page has actually left the ground. */
.night { background: var(--navy); color: var(--haze); }
.night h1, .night h2, .night h3, .night h4 { color: var(--cream); }
.night strong { color: var(--cream); }
.night a { color: var(--mint); }
.night a:hover { color: var(--cream); }
.night .eyebrow { color: var(--gold); }
.night code { color: var(--cream); }

/* ─── Cloud bank ─────────────────────────────────────────────────────────
   The motif that ties the page to the badge: the logo stands its wordmark on
   a bank of clouds, so every major seam here is that same bank. Not a soft
   gradient fade — that is what every other site does, and it throws away the
   one shape this brand actually owns. */
.clouds { display: block; width: 100%; height: auto; }
.clouds.flip { transform: scaleY(-1); }
.seam { position: relative; line-height: 0; }
.seam svg { display: block; width: 100%; height: auto; }

/* ─── Nav ──────────────────────────────────────────────────────────────── */
.nav {
  position: sticky; top: 0; z-index: 50;
  background: color-mix(in srgb, var(--white) 88%, transparent);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--line);
}
.nav-in { display: flex; align-items: center; gap: 1.5rem; min-height: 74px; }
.brand { margin-right: auto; display: flex; align-items: center; text-decoration: none; }
/* 40px, not 24px. The badge is an illustration with a wordmark inside it and
   below roughly 32px its lettering stops being readable — a logo nobody can
   read is a decoration taking up the corner. */
.brand img { height: 40px; width: auto; }
.nav-links { display: flex; gap: 1.5rem; align-items: center; }
.nav-links a {
  font: 700 .95rem/1 var(--display);
  color: var(--ink-soft); text-decoration: none;
  padding: .45rem .1rem; border-bottom: 2px solid transparent;
  transition: color .15s, border-color .15s;
}
.nav-links a:hover { color: var(--ink); border-bottom-color: var(--sky); }
.nav-links a[aria-current='page'] { color: var(--ink); border-bottom-color: var(--gold); }

@media (max-width: 640px) {
  .nav-in { flex-wrap: wrap; min-height: 0; padding-block: .8rem; gap: .7rem 1.2rem; }
  .brand { margin-right: 0; width: 100%; }
  .brand img { height: 34px; }
  .nav-links { gap: 1.2rem; }
  .nav-links a { font-size: .88rem; }
}

/* ─── Buttons ──────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .55rem;
  font: 700 1rem/1 var(--display);
  padding: .9rem 1.6rem;
  border-radius: 999px;
  border: 2px solid var(--ink);
  background: transparent; color: var(--ink);
  text-decoration: none; cursor: pointer;
  transition: background .15s, color .15s, transform .1s;
}
.btn:hover { background: var(--ink); color: var(--cream); }
.btn:active { transform: translateY(1px); }

/* Hard bottom edge, not a blur. The badge is drawn with flat outlined shapes
   and no soft shadows anywhere in it; a diffuse drop-shadow here would be the
   one un-illustrated thing on the page. */
.btn-primary {
  background: var(--gold); border-color: var(--ink); color: var(--ink);
  box-shadow: 0 3px 0 var(--ink);
}
.btn-primary:hover { background: #FFD26B; color: var(--ink); }
.btn-primary:active { box-shadow: 0 1px 0 var(--ink); transform: translateY(2px); }

.night .btn { border-color: var(--cream); color: var(--cream); }
.night .btn:hover { background: var(--cream); color: var(--ink); }
.night .btn-primary { border-color: var(--gold); color: var(--ink); box-shadow: 0 3px 0 #8A5F12; }

.btn[aria-disabled='true'] {
  border-color: var(--line); background: transparent;
  color: var(--ink-faint); cursor: not-allowed; pointer-events: none; box-shadow: none;
}
.night .btn[aria-disabled='true'] { border-color: var(--navy-edge); color: var(--ink-faint); }

/* ─── Hero ─────────────────────────────────────────────────────────────── */
.hero { padding-block: clamp(2.5rem, 6vw, 4.5rem) clamp(2rem, 4vw, 3rem); overflow: hidden; }
.hero h1 { margin-bottom: 1.3rem; text-wrap: balance; }
.hero h1 .l2 { display: block; color: var(--sky-deep); }
.hero-lead { font-size: clamp(1.05rem, .98rem + .4vw, 1.2rem); max-width: 44ch; }

.hero-split {
  display: grid; grid-template-columns: minmax(0,1fr) 16rem;
  gap: clamp(2rem, 5vw, 4rem); align-items: center;
}
@media (max-width: 920px) { .hero-split { grid-template-columns: 1fr; } .hero-badge { display: none; } }
/* logo-mark.svg paints a full SQUARE dark plate — unlike the rank badges,
   which are drawn with their own rounded corners. A drop-shadow follows the
   alpha and so does nothing for a square: it just makes a dark rectangle look
   like a dark rectangle with a shadow. The radius has to be applied here, and
   then it reads as the app icon it is. */
.hero-badge {
  width: 100%; height: auto;
  border-radius: 26px;
  box-shadow: 0 6px 0 rgba(3,18,43,.20);
}

/* Daylight sky: warm near the horizon, cooler overhead. The old version was a
   near-black field with a star layer; this is the same gradient turned right
   way up. */
.sky-bg {
  position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background:
    radial-gradient(130% 74% at 50% 120%, rgba(250,244,235,.95), transparent 60%),
    radial-gradient(90% 55% at 84% 4%, rgba(114,179,227,.30), transparent 64%),
    linear-gradient(180deg, #D9EBF9 0%, var(--day) 55%);
}
.stars { display: none; }        /* daylight. Kept so old markup does not break. */

/* The address — the one string the whole page exists to get copied, so it is
   the one dark object in a bright hero. */
.addr {
  display: flex; align-items: stretch; flex-wrap: wrap;
  margin: 2rem 0 .85rem; max-width: 30rem;
  border: 2px solid var(--ink); border-radius: 14px;
  background: var(--ink); overflow: hidden;
  box-shadow: 0 3px 0 rgba(3,18,43,.22);
}
.addr-val {
  flex: 1 1 auto; min-width: 0; display: flex; align-items: center;
  font: 600 clamp(1.05rem, .92rem + .8vw, 1.35rem)/1 var(--mono);
  color: var(--cream); padding: 1rem 1.15rem; word-break: break-all;
}
.addr-copy {
  flex: 0 0 auto; border: 0; border-left: 2px solid rgba(250,244,235,.22);
  background: transparent; color: var(--gold);
  font: 700 .92rem/1 var(--display); padding-inline: 1.3rem; cursor: pointer;
  transition: background .15s, color .15s;
}
.addr-copy:hover { background: rgba(247,189,70,.16); }
.addr-copy[data-done='1'] { color: var(--mint); }

.ports { font: 500 .87rem/1.5 var(--mono); color: var(--ink-faint);
         display: flex; flex-wrap: wrap; gap: .3rem 1.5rem; }
.ports b { color: var(--ink-soft); font-weight: 600; }

/* ─── SIGNATURE: the market strip ────────────────────────────────────────
   "Dynamic Economy" is half the tagline, so the home page shows the economy
   actually moving rather than asserting that it does. The
   items are real catalogue entries and the direction of travel is real —
   selling pushes a price down, scarcity pulls it up. The NUMBERS are
   illustrative and the panel says so out loud. A fake live feed would be a
   lie; a labelled demonstration of the mechanic is the honest version of the
   same idea, and it is the one element here no other server site has. */
.market {
  margin-top: 2.4rem; max-width: 34rem;
  border: 2px solid var(--ink); border-radius: 16px;
  background: var(--white); overflow: hidden;
  box-shadow: 0 3px 0 rgba(3,18,43,.14);
}
.market-hd {
  display: flex; align-items: baseline; gap: .55rem; flex-wrap: wrap;
  padding: .8rem 1.1rem; border-bottom: 2px solid var(--ink);
  background: var(--day-warm);
}
.market-hd b { font: 700 .95rem/1 var(--display); color: var(--ink); }
.market-hd span { font-size: .78rem; color: var(--ink-faint); }
.market-list { list-style: none; margin: 0; padding: .35rem 0 .55rem; }
.market-list li {
  display: grid; grid-template-columns: 1fr auto 2.8rem;
  gap: .8rem; align-items: center; padding: .45rem 1.1rem;
}
.market-item { color: var(--ink-soft); font-size: .95rem; }
.market-price {
  font: 600 .98rem/1 var(--mono); color: var(--ink); text-align: right;
  font-variant-numeric: tabular-nums;
}
.market-dir { font: 700 .82rem/1 var(--display); text-align: right; }
.market-dir.up { color: var(--mint-deep); }
.market-dir.dn { color: #C4553F; }

/* ─── Feature cards ────────────────────────────────────────────────────── */
.grid {
  display: grid; gap: 1rem; margin-top: 2.6rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
}
.cell {
  background: var(--white); border: 2px solid var(--ink);
  border-radius: 16px; padding: 1.6rem 1.5rem;
  box-shadow: 0 3px 0 rgba(3,18,43,.13);
  transition: transform .16s, box-shadow .16s;
}
.cell:hover { transform: translateY(-3px); box-shadow: 0 6px 0 rgba(3,18,43,.13); }
.cell h3 { margin-bottom: .5rem; }
.cell p { font-size: .95rem; margin: 0; color: var(--ink-soft); }
.cell .tag {
  display: inline-block; margin-bottom: .85rem;
  font: 700 .68rem/1 var(--display); letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink); background: var(--sky);
  padding: .34rem .6rem; border-radius: 99px;
}
.night .cell { background: var(--navy-deep); border-color: var(--navy-edge); box-shadow: none; }
.night .cell p { color: var(--haze); }

/* ─── THE CLIMB ──────────────────────────────────────────────────────────
   The ranks are named for altitude, so the store is an ascent — and now it is
   drawn as one. Cloud sits in daylight; each tier's ground darkens until
   Celestial is deep space. That is the real sky, it matches the badge art
   (a white cumulus at the bottom, a gold star on black at the top), and it is
   what makes the dark on this site feel earned instead of default. */
.climb { padding: 0; }

.tier { position: relative; padding-block: clamp(2.4rem, 4.5vw, 3.6rem); }
.tier[data-band='cloud']     { --band: var(--t-cloud);     --bg: #DCEDFA; --fg: var(--ink);   --sub: var(--ink-soft); --chip: #FFFFFF; --chipline: var(--line); }
.tier[data-band='storm']     { --band: var(--t-storm);     --bg: #BBD4EE; --fg: var(--ink);   --sub: var(--ink-soft); --chip: #FFFFFF; --chipline: #A8C4E2; }
.tier[data-band='aurora']    { --band: var(--t-aurora);    --bg: #6E9BC4; --fg: #04162E;      --sub: #14304F;        --chip: #E8F3FC; --chipline: #8FB4D6; }
.tier[data-band='nebula']    { --band: #B79BF0;            --bg: #2A3C6B; --fg: var(--cream); --sub: #C3D3EA;        --chip: #1B2A50; --chipline: #45599A; }
.tier[data-band='celestial'] { --band: var(--gold);        --bg: #0A1730; --fg: var(--cream); --sub: var(--haze);    --chip: #05101F; --chipline: #23375F; }

.tier { background: var(--bg); color: var(--sub); }
.tier h3 { color: var(--fg); }

.tier-in { display: grid; grid-template-columns: 7.5rem minmax(0,1fr); gap: 0 1.9rem; align-items: start; }
.tier-art {
  width: 7.5rem; height: 7.5rem;
  filter: drop-shadow(0 4px 0 rgba(3,18,43,.22));
}
@media (max-width: 720px) {
  .tier-in { grid-template-columns: 1fr; gap: 1rem; }
  .tier-art { width: 5.5rem; height: 5.5rem; }
}

.tier-head { display: flex; align-items: center; flex-wrap: wrap; gap: .5rem 1rem; margin-bottom: .6rem; }
.tier-name { font: 800 clamp(1.7rem,1.3rem+1.6vw,2.4rem)/1 var(--display); color: var(--fg); }
.tier-alt { font: 500 .78rem/1 var(--mono); color: var(--sub); opacity: .85; }
.tier-price { margin-left: auto; font: 800 1.45rem/1 var(--display); color: var(--fg); }
.tier-sell { color: var(--fg); font-size: 1.02rem; max-width: 46ch; margin-bottom: 1.1rem; }

.tier-specs { display: flex; flex-wrap: wrap; gap: .45rem; margin: 0 0 1.4rem; padding: 0; list-style: none; }
.tier-specs li {
  font-size: .82rem; color: var(--sub);
  border: 1px solid var(--chipline); background: var(--chip);
  border-radius: 99px; padding: .38rem .75rem;
}
.tier-specs li b { color: var(--fg); font-weight: 700; }
.tier-specs li.wep { border-color: var(--band); }
.tier-specs li.wep b { color: var(--band); }

.tier-cta { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; }
.tier-note { font-size: .85rem; color: var(--sub); opacity: .9; }

/* Buttons have to invert with the band, not with the page. */
.tier[data-band='nebula'] .btn,
.tier[data-band='celestial'] .btn { border-color: var(--cream); color: var(--cream); }
.tier[data-band='nebula'] .btn:hover,
.tier[data-band='celestial'] .btn:hover { background: var(--cream); color: var(--ink); }
.tier .btn-primary { background: var(--gold); border-color: var(--ink); color: var(--ink); box-shadow: 0 3px 0 var(--ink); }

@media (max-width: 620px) { .tier-price { margin-left: 0; width: 100%; } }

/* ─── Table ────────────────────────────────────────────────────────────── */
.tablewrap { overflow-x: auto; margin-top: 2.2rem; border: 2px solid var(--ink); border-radius: 14px; background: var(--white); }
table { border-collapse: collapse; width: 100%; min-width: 44rem; font-size: .9rem; }
th, td { padding: .7rem .9rem; text-align: left; border-bottom: 1px solid var(--line); }
thead th {
  font: 700 .78rem/1 var(--display); text-transform: uppercase; letter-spacing: .06em;
  color: var(--ink); background: var(--day-warm); position: sticky; top: 0; white-space: nowrap;
}
tbody th { font-weight: 400; color: var(--ink-soft); font-size: .9rem; font-family: var(--body); }
td { text-align: center; font-family: var(--mono); font-size: .82rem; color: var(--ink-soft); }
tbody tr:hover { background: var(--day); }
tbody tr:last-child th, tbody tr:last-child td { border-bottom: 0; }
.yes { color: var(--mint-deep); font-weight: 600; } .no { color: var(--ink-faint); }

/* ─── Vote list ────────────────────────────────────────────────────────── */
.votes { list-style: none; padding: 0; margin: 2.2rem 0 0; display: grid; gap: .65rem; }
.vote-row {
  display: flex; align-items: center; gap: 1rem; flex-wrap: wrap;
  padding: 1rem 1.25rem; text-decoration: none; color: inherit;
  background: var(--white); border: 2px solid var(--ink); border-radius: 14px;
  box-shadow: 0 3px 0 rgba(3,18,43,.13);
  transition: transform .15s, box-shadow .15s;
}
a.vote-row:hover { transform: translateY(-2px); box-shadow: 0 5px 0 rgba(3,18,43,.13); }
.vote-n { font: 600 .8rem/1 var(--mono); color: var(--ink-faint); min-width: 1.7rem; }
.vote-name { font: 700 1.05rem/1.2 var(--display); color: var(--ink); }
.vote-note { font-size: .82rem; color: var(--ink-faint); }
.vote-go { margin-left: auto; font: 700 .85rem/1 var(--display); color: var(--gold-deep); white-space: nowrap; }
.vote-row[aria-disabled='true'] { cursor: not-allowed; background: var(--day); box-shadow: none; border-style: dashed; }
.vote-row[aria-disabled='true'] .vote-go { color: var(--ink-faint); }

/* ─── Rules ────────────────────────────────────────────────────────────── */
.rules { counter-reset: rule; list-style: none; padding: 0; margin: 2.2rem 0 0; display: grid; gap: .85rem; }
.rules > li {
  counter-increment: rule; position: relative;
  background: var(--white); border: 2px solid var(--ink); border-radius: 16px;
  box-shadow: 0 3px 0 rgba(3,18,43,.13);
  padding: 1.4rem 1.5rem 1.4rem 4.6rem;
}
.rules > li::before {
  content: counter(rule);
  position: absolute; left: 1.35rem; top: 1.35rem;
  width: 2.3rem; height: 2.3rem; border-radius: 50%;
  background: var(--sky); color: var(--ink); border: 2px solid var(--ink);
  display: grid; place-items: center;
  font: 800 1rem/1 var(--display);
}
.rules h3 { margin-bottom: .35rem; }
.rules p { font-size: .96rem; margin: 0; color: var(--ink-soft); }

/* ─── Callout ──────────────────────────────────────────────────────────── */
.note {
  border: 2px solid var(--ink); border-left-width: 8px;
  background: var(--day-warm);
  padding: 1.15rem 1.35rem; margin: 2rem 0 0; border-radius: 14px;
}
.note p { font-size: .95rem; color: var(--ink-soft); }
.note strong { color: var(--ink); }
.night .note { background: var(--navy-deep); border-color: var(--gold); }
.night .note p { color: var(--haze); }
.night .note strong { color: var(--gold); }

/* ─── Footer ─────────────────────────────────────────────────────────────
   Night, deliberately: it is the void the island floats in, and it gives the
   page a floor. */
.foot { background: var(--navy-deep); color: var(--haze); padding-block: 3rem 3.5rem; }
.foot-in { display: flex; gap: 1.6rem 3rem; flex-wrap: wrap; align-items: flex-start; }
.foot-brand img { height: 48px; width: auto; }
.foot-tag { font: 600 .95rem/1.5 var(--display); color: var(--sky); margin-top: .7rem; }
.foot-links { display: flex; gap: 1.4rem; flex-wrap: wrap; margin-left: auto; }
.foot-links a { font: 700 .95rem/1 var(--display); color: var(--haze); text-decoration: none; }
.foot-links a:hover { color: var(--gold); }
.foot-legal { font-size: .8rem; color: #6E88AB; margin-top: 2rem; max-width: 62ch; }

/* ─── Reveal ───────────────────────────────────────────────────────────── */
.rise { opacity: 0; transform: translateY(16px); transition: opacity .5s ease, transform .5s ease; }
.rise.in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) { .rise { opacity: 1; transform: none; } }

/* ─── Rank strip (home page teaser) ──────────────────────────────────────
   The five badges in a row, which is the whole ladder in one glance. They
   are the argument for clicking through, so they get to be large. */
.rank-strip {
  list-style: none; margin: 2.4rem 0 0; padding: 0;
  display: grid; gap: 1rem;
  grid-template-columns: repeat(5, minmax(0, 1fr));
}
.rank-strip li { text-align: center; }
.rank-strip img {
  width: 100%; height: auto; max-width: 7rem; margin-inline: auto;
  transition: transform .18s;
}
.rank-strip li:hover img { transform: translateY(-4px) scale(1.04); }
.rank-strip span {
  display: block; margin-top: .5rem;
  font: 700 .82rem/1 var(--display); color: var(--ink-soft);
}
@media (max-width: 640px) {
  .rank-strip { grid-template-columns: repeat(3, 1fr); gap: 1.2rem .8rem; }
  .rank-strip span { font-size: .75rem; }
}

/* Seam SVGs sit flush against the section below them. */
.seam { margin-bottom: -1px; }

/* A disabled control has to stay legible on every band. The page-level grey
   (--ink-faint) is almost exactly Aurora's background, so inside the climb the
   disabled button borrows the band's own text colour instead. */
.tier .btn[aria-disabled='true'] {
  color: var(--sub);
  border-color: var(--chipline);
  background: color-mix(in srgb, var(--chip) 60%, transparent);
  opacity: .9;
}
.tier .tier-note { opacity: 1; }

/* ══════════════════════════════════════════════════════════════════════════
   LOUD LAYER
   Appended deliberately rather than merged into the tokens above, so the
   quiet base stays readable on its own and everything that raises the volume
   is in one place you can turn down again.

   THE RULE THAT KEEPS LOUD USABLE: shout in the display layer, stay calm in
   the reading layer. Headlines, badges and motion get bigger and busier;
   paragraphs, chips, tables and form controls do not move at all. A site
   where the body copy is also shouting is not loud, it is unreadable.
   ══════════════════════════════════════════════════════════════════════════ */

/* ─── The wordmark treatment, as type ────────────────────────────────────
   The badge is cream letters inside a thick navy outline. That is a
   construction, not just a colour, so it can be rebuilt in CSS and applied to
   a headline — which makes the loudest element on the page also the most
   on-brand one.

   paint-order:stroke fill is what puts the outline BEHIND the glyph instead
   of eating into it. Without it the stroke grows inward and the letterforms
   go muddy at weight; browsers that lack it still get a readable heavy
   headline, just a slightly tighter one. */
.shout {
  color: var(--cream);
  -webkit-text-stroke: .1em var(--ink);
  paint-order: stroke fill;
  text-shadow: 0 .055em 0 var(--ink);
  letter-spacing: -.02em;
  line-height: .96;
}
.shout-sky { color: var(--sky); }
.shout-gold { color: var(--gold); }

/* On night grounds the outline has to invert or it vanishes into the dark. */
.night .shout, .tier[data-band='nebula'] .shout, .tier[data-band='celestial'] .shout {
  -webkit-text-stroke-color: #000;
  text-shadow: 0 .055em 0 #000;
}

/* ─── Volume ─────────────────────────────────────────────────────────────
   The hero headline stops sharing a row with anything, so it can take the
   whole measure. */
.hero h1 {
  font-size: clamp(3.2rem, 1.2rem + 9.4vw, 9rem);
  margin-bottom: 1.5rem;
}
.hero h1 .l2 { display: block; }
h2 { font-size: clamp(2.2rem, 1.5rem + 3vw, 4rem); }
.hero-lead { font-size: clamp(1.1rem, 1rem + .55vw, 1.4rem); max-width: 48ch; }

/* ─── Drifting cloud field ───────────────────────────────────────────────
   Three layers at three speeds. The parallax is the point: one layer of
   clouds is wallpaper, three at different rates reads as depth and as sky.
   Pointer-events off and aria-hidden in the markup — this is scenery, and a
   screen reader announcing six clouds would be worse than silence. */
.cloud-field { position: absolute; inset: 0; overflow: hidden; z-index: -1; pointer-events: none; }
.cloud-field img, .cloud-field svg { position: absolute; opacity: .9; will-change: transform; }

@keyframes drift-r { from { transform: translateX(-22vw); } to { transform: translateX(122vw); } }
@keyframes bob     { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-14px); } }
@keyframes twinkle { 0%,100% { opacity: .25; transform: scale(.85) rotate(0deg); } 50% { opacity: 1; transform: scale(1.15) rotate(45deg); } }
@keyframes sway    { 0%,100% { transform: rotate(-1.4deg); } 50% { transform: rotate(1.4deg); } }

.c1 { top: 12%;  width: 190px; animation: drift-r 78s linear infinite; }
.c2 { top: 34%;  width: 130px; opacity: .65; animation: drift-r 116s linear infinite -30s; }
.c3 { top: 62%;  width: 250px; opacity: .8;  animation: drift-r 96s linear infinite -60s; }
.c4 { top: 6%;   width: 100px; opacity: .5;  animation: drift-r 140s linear infinite -95s; }

/* ─── Things that float ──────────────────────────────────────────────────
   The badge bobs because it is a sticker on a sky, not a photograph. One
   element doing this is charm; every element doing it is a fairground. */
.hero-badge { animation: bob 5.5s ease-in-out infinite; }
.tier-art   { animation: bob 6.5s ease-in-out infinite; }
.tier:nth-child(2) .tier-art { animation-delay: -1.2s; }
.tier:nth-child(3) .tier-art { animation-delay: -2.4s; }
.tier:nth-child(4) .tier-art { animation-delay: -3.6s; }
.tier:nth-child(5) .tier-art { animation-delay: -4.8s; }
.rank-strip li:nth-child(2) img { animation-delay: -.9s; }
.rank-strip li:nth-child(3) img { animation-delay: -1.8s; }
.rank-strip li:nth-child(4) img { animation-delay: -2.7s; }
.rank-strip li:nth-child(5) img { animation-delay: -3.6s; }
.rank-strip img { animation: bob 6s ease-in-out infinite; }

/* ─── Stickers ───────────────────────────────────────────────────────────
   Cards get a small rotation so the page reads as things placed on a surface
   rather than boxes in a grid. Alternating direction, and it straightens on
   hover — which gives the hover somewhere to go. */
.cell:nth-child(odd)  { transform: rotate(-.7deg); }
.cell:nth-child(even) { transform: rotate(.7deg); }
.cell { box-shadow: 0 5px 0 rgba(3,18,43,.16); }
.cell:hover { transform: rotate(0deg) translateY(-6px); box-shadow: 0 11px 0 rgba(3,18,43,.16); }

.rules > li:nth-child(odd)  { transform: rotate(-.35deg); }
.rules > li:nth-child(even) { transform: rotate(.35deg); }
.rules > li { transition: transform .16s; }
.rules > li:hover { transform: rotate(0deg); }

.vote-row { box-shadow: 0 4px 0 rgba(3,18,43,.16); }
a.vote-row:hover { transform: translateY(-3px) rotate(-.5deg); box-shadow: 0 8px 0 rgba(3,18,43,.16); }

/* ─── Bigger art ─────────────────────────────────────────────────────────
   The badges are the best thing the brand owns. They were being used at the
   size of an icon; here they are used at the size of an argument. */
.hero-badge { border-radius: 34px; box-shadow: 0 10px 0 rgba(3,18,43,.22); }
.tier-in { grid-template-columns: 12rem minmax(0,1fr); gap: 0 2.6rem; }
.tier-art { width: 12rem; height: 12rem; filter: drop-shadow(0 7px 0 rgba(3,18,43,.24)); }
.rank-strip img { max-width: 11rem; }
.tier { padding-block: clamp(3rem, 6vw, 4.8rem); }

@media (max-width: 780px) {
  .tier-in { grid-template-columns: 1fr; gap: 1.2rem; }
  .tier-art { width: 8rem; height: 8rem; }
}

/* ─── Loud buttons ───────────────────────────────────────────────────────
   Chunkier, with a deeper edge, and they press properly. */
.btn { font-size: 1.12rem; padding: 1.05rem 2rem; border-width: 3px; }
.btn-primary { box-shadow: 0 5px 0 var(--ink); }
.btn-primary:hover { transform: translateY(-2px); box-shadow: 0 7px 0 var(--ink); }
.btn-primary:active { transform: translateY(3px); box-shadow: 0 2px 0 var(--ink); }

.addr { border-width: 3px; box-shadow: 0 5px 0 rgba(3,18,43,.24); }
.market { border-width: 3px; box-shadow: 0 5px 0 rgba(3,18,43,.16); }
.cell, .rules > li, .vote-row, .tablewrap { border-width: 3px; }

/* ─── Eyebrow as a sticker label ─────────────────────────────────────── */
.eyebrow {
  display: inline-block;
  background: var(--gold); color: var(--ink);
  border: 2px solid var(--ink);
  border-radius: 99px;
  padding: .42rem .95rem;
  font-size: .78rem; letter-spacing: .14em;
  box-shadow: 0 3px 0 var(--ink);
  transform: rotate(-1.5deg);
  margin-bottom: 1.3rem;
}
.night .eyebrow { border-color: #000; box-shadow: 0 3px 0 #000; }

/* ─── Reveal with some character ─────────────────────────────────────────
   Up, and slightly out of scale, so arriving elements have a bit of weight
   to them. Still one effect, still fired once. */
.rise { opacity: 0; transform: translateY(30px) scale(.97); transition: opacity .55s cubic-bezier(.2,.7,.3,1), transform .55s cubic-bezier(.2,.7,.3,1); }
.rise.in { opacity: 1; transform: none; }

/* ─── The whole loud layer switches off for reduced motion ───────────────
   The blanket rule at the top of this file already collapses durations, but
   an infinite animation with a 0.001ms duration still repaints forever. These
   are turned off outright, and the sticker rotations are straightened so the
   page is genuinely still rather than merely fast. */
@media (prefers-reduced-motion: reduce) {
  .cloud-field { display: none; }
  .hero-badge, .tier-art, .rank-strip img { animation: none; }
  .cell, .rules > li, .eyebrow { transform: none !important; }
  .rise { opacity: 1; transform: none; }
}

/* ─── Hero headline, full measure ────────────────────────────────────────
   Lifted out of the two-column split. Inside the column it wrapped to four
   lines, which reads as a mistake rather than as emphasis; across the whole
   shell it lands on two, which is the shape the line was written for. */
.hero-shout { max-width: none; margin-bottom: 2rem; }
.hero .hero-split { align-items: start; padding-top: 0; }

/* Clouds want to be seen. At the previous size and opacity they were closer
   to noise in the gradient than to weather. */
.c1 { top: 6%;   width: 260px; }
.c2 { top: 30%;  width: 180px; opacity: .75; }
.c3 { top: 58%;  width: 330px; opacity: .85; }
.c4 { top: 78%;  width: 150px; opacity: .6; }

/* ─── The tier name is the loudest thing in its row ──────────────────────
   It was set small and flat, which left the badge and the price shouting
   over the one word that says what you are buying. Same outlined
   construction as the hero, sized to match the artwork beside it. */
.tier-name {
  font-size: clamp(2.2rem, 1.5rem + 2.6vw, 3.6rem);
  color: var(--cream);
  -webkit-text-stroke: .085em var(--ink);
  paint-order: stroke fill;
  text-shadow: 0 .05em 0 var(--ink);
  letter-spacing: -.02em;
}
/* On the two night bands the ink outline disappears into the background, so
   it goes black and the fill takes the band's own colour. */
.tier[data-band='nebula'] .tier-name,
.tier[data-band='celestial'] .tier-name {
  color: var(--band);
  -webkit-text-stroke-color: #000;
  text-shadow: 0 .05em 0 #000;
}

.tier-price {
  font-size: clamp(1.6rem, 1.2rem + 1.4vw, 2.4rem);
  color: var(--cream);
  -webkit-text-stroke: .07em var(--ink);
  paint-order: stroke fill;
  text-shadow: 0 .05em 0 var(--ink);
}
.tier[data-band='nebula'] .tier-price,
.tier[data-band='celestial'] .tier-price {
  color: var(--gold);
  -webkit-text-stroke-color: #000;
  text-shadow: 0 .05em 0 #000;
}

.tier-alt {
  font-size: .82rem;
  background: color-mix(in srgb, var(--chip) 75%, transparent);
  border: 1px solid var(--chipline);
  border-radius: 99px; padding: .3rem .7rem;
}
.tier-sell { font-size: 1.12rem; }

/* ─── Who the purchase is for ────────────────────────────────────────────
   Above the ladder and before any price, because it is the field that decides
   whether the money reaches the right account. It used to be a prompt() that
   only appeared after clicking Buy, which meant the most consequential input
   on the page was also the least visible. */
.whoami {
  display: flex; align-items: center; gap: .8rem; flex-wrap: wrap;
  background: var(--white); border: 3px solid var(--ink); border-radius: 16px;
  box-shadow: 0 4px 0 rgba(3,18,43,.16);
  padding: 1rem 1.2rem; margin-bottom: 2rem;
}
.whoami label {
  font: 700 1rem/1 var(--display); color: var(--ink); white-space: nowrap;
}
.whoami input {
  flex: 1 1 14rem; min-width: 0;
  font: 600 1.05rem/1 var(--mono); color: var(--ink);
  background: var(--day); border: 2px solid var(--line); border-radius: 10px;
  padding: .75rem .9rem;
}
.whoami input:focus { outline: none; border-color: var(--sky-deep); background: #fff; }
.whoami input[aria-invalid='true'] { border-color: #C4553F; background: #FFF3F1; }
.whoami-note { flex: 1 1 100%; font-size: .85rem; color: var(--ink-faint); }
.whoami-note[data-state='ok']    { color: var(--mint-deep); font-weight: 600; }
.whoami-note[data-state='error'] { color: #C4553F; font-weight: 600; }

/* The player's face, so they can SEE it is them before paying. */
.whoami-face {
  width: 56px; height: 56px; flex: 0 0 auto;
  border: 3px solid var(--ink); border-radius: 12px;
  image-rendering: pixelated;          /* it is 8x8 upscaled — keep it crisp */
  background: var(--day);
  box-shadow: 0 3px 0 rgba(3,18,43,.16);
}
@media (max-width: 520px) { .whoami-face { width: 44px; height: 44px; } }

/* ══════════════════════════════════════════════════════════════════════════
   CRATE KEYS
   ──────────────────────────────────────────────────────────────────────────
   THE CRATE COLOURS BELOW ARE NOT BRAND COLOURS. They are the colours the
   crates already have in game (config/crates/crates.yml: white, aqua,
   light_purple, gold), so a player who has seen a Legendary Crate at spawn
   recognises the gold one here without reading. Violet appears nowhere else on
   this site and is not in the logo - it is here because `epic` is
   <light_purple> in game, and matching that is worth more than palette purity.

   The odds bar is the point of this page. Crate odds are normally hidden, and
   a server that publishes them is making a claim about itself. The widths are
   the real chances, not decoration.
   ══════════════════════════════════════════════════════════════════════════ */
:root {
  --crate-common:    #FFFFFF;
  --crate-rare:      #72B3E3;
  --crate-epic:      #7A5CC4;   /* --t-nebula: the palette's only purple */
  --crate-legendary: #F7BD46;
}

.keys { display: grid; gap: 1.5rem; }
@media (min-width: 900px) { .keys { grid-template-columns: 1fr 1fr; } }

.crate {
  background: var(--white);
  border: 3px solid var(--ink);
  border-radius: 1.1rem;
  box-shadow: 0 .35rem 0 var(--ink);
  padding: 1.4rem 1.4rem 1.2rem;
  display: flex; flex-direction: column; gap: .95rem;
}

.crate-hd { display: flex; align-items: baseline; gap: .6rem; flex-wrap: wrap; }
.crate-name {
  font-family: 'Baloo 2', system-ui, sans-serif;
  font-size: clamp(1.5rem, 3.4vw, 2.05rem);
  line-height: 1; letter-spacing: -.01em;
  color: var(--dot); -webkit-text-stroke: .055em var(--ink); paint-order: stroke fill;
  text-shadow: 0 .045em 0 var(--ink);
}
.crate-tag { font-size: .8rem; color: var(--ink-faint); font-weight: 700; }

/* The odds bar. Segment widths are the real drop chances. */
.odds {
  display: flex; height: 1.05rem; overflow: hidden;
  border: 3px solid var(--ink); border-radius: 999px; background: var(--day);
}
.odds > i { display: block; height: 100%; }
.odds > i + i { border-left: 2px solid var(--ink); }
.odds-money { background: var(--mint); }
.odds-xp    { background: var(--sky); }
.odds-ench  { background: var(--dot); }
.odds-prot  { background: var(--day-warm); }
.odds-next  { background: var(--gold); }

.odds-legend {
  display: flex; flex-wrap: wrap; gap: .35rem .9rem;
  font-size: .76rem; font-weight: 700; color: var(--ink-soft); margin: 0; padding: 0; list-style: none;
}
.odds-legend li { display: flex; align-items: center; gap: .34rem; }
.odds-legend i {
  width: .72rem; height: .72rem; border: 2px solid var(--ink);
  border-radius: .18rem; flex: none;
}
.odds-legend b { color: var(--ink); font-variant-numeric: tabular-nums; }

.crate-pool { margin: 0; font-size: .92rem; color: var(--ink-soft); line-height: 1.5; }
.crate-pool b { color: var(--ink); }

.buy-row { display: flex; gap: .6rem; flex-wrap: wrap; margin-top: auto; padding-top: .3rem; }
.buy-row .btn { flex: 1 1 auto; text-align: center; white-space: nowrap; }
.buy-row .btn small { display: block; font-weight: 700; opacity: .75; font-size: .74rem; }

.crate-note { font-size: .78rem; color: var(--ink-faint); margin: 0; }
.crate-note[data-kind="error"] { color: #B3261E; font-weight: 700; }
.crate-note[data-kind="ok"]    { color: var(--mint-deep); font-weight: 700; }
