:root {
  /* Tells the browser this is a dark page. Without it the browser assumes
     light and paints a white canvas in every gap it controls: the blank frame
     while a link is loading — including on the way out to Discord — the moment
     before the stylesheet arrives, plus scrollbars and form controls, which
     were rendering in light chrome on a near-black page. */
  color-scheme: dark;

  --bg: #0a0c14;
  --panel: #121624;
  --panel-2: #171c2e;
  --line: #232a42;
  --text: #e8ecf8;
  --muted: #8e97b4;
  --accent: #4d7cff;
  --accent-2: #7aa2ff;
  --gold: #ffc63d;
  --green: #4ade80;

  /* motion */
  --ease: cubic-bezier(.16,1,.3,1);
  --dur-fast: .15s;
  --dur-med: .35s;
  --dur-slow: .7s;

  /* elevation */
  --shadow-sm: 0 1px 2px rgba(0,0,0,.35);
  --shadow-md: 0 16px 32px -12px rgba(0,0,0,.55);
  --shadow-lg: 0 28px 60px -16px rgba(0,0,0,.65);
  --glow: 0 0 0 1px rgba(77,124,255,.2), 0 12px 32px -10px rgba(77,124,255,.4);
}

* { box-sizing: border-box; margin: 0; padding: 0; }

/* Any class setting its own `display` (flex/grid/etc.) otherwise silently
   beats the browser's default [hidden]{display:none} — author CSS always
   wins over the UA stylesheet regardless of selector specificity. This bit
   us three separate times (.btn, .guestbanner, .chips/.pager/.avatar-fallback)
   before it became worth fixing once, globally, instead of per class. */
[hidden] { display: none !important; }

/* The header is sticky and 65px tall, so an anchor jump would otherwise put
   the section heading underneath it. scroll-padding-top on the root fixes
   every in-page link at once — nav anchors and deep links like
   /learn#practice — instead of needing scroll-margin on each target. */
html { scroll-behavior: smooth; scroll-padding-top: 78px; }

body {
  position: relative;   /* anchors .page-glow */
  background: var(--bg);
  color: var(--text);
  font-family: ui-sans-serif, -apple-system, "Segoe UI", Inter, system-ui, sans-serif;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  /* Without this, a page shorter than the viewport (CodeType's minimal,
     spacious layout is the first one short enough to hit it) ends before
     the viewport does, and the browser's own default canvas color shows
     through below — a grey band that has nothing to do with our theme. */
  min-height: 100vh;
}

a { color: var(--accent-2); text-decoration: none; transition: color var(--dur-fast) var(--ease); }
a:hover { text-decoration: underline; }

:focus-visible { outline: 2px solid var(--accent-2); outline-offset: 3px; border-radius: 4px; }

.wrap { max-width: 1240px; margin: 0 auto; padding: 0 32px; }

/* .reveal is inert now. Content used to start invisible and fade in when it
   crossed the viewport, which meant anything already on screen popped in a
   beat late and scrolling constantly triggered movement. The class is left on
   the markup so nothing needs restructuring; it just no longer hides anything. */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important; animation-iteration-count: 1 !important;
    transition-duration: .001ms !important; scroll-behavior: auto !important;
  }
}

/* header */
header {
  position: sticky; top: 0; z-index: 10;
  border-bottom: 1px solid rgba(255,255,255,.05);
  background: rgba(13,17,30,.52);
  /* saturate() is what stops a blurred dark bar looking like flat grey — it
     keeps the colour of whatever is scrolling underneath it */
  backdrop-filter: blur(20px) saturate(170%);
  -webkit-backdrop-filter: blur(20px) saturate(170%);
  transition: background var(--dur-med) var(--ease), border-color var(--dur-med) var(--ease), box-shadow var(--dur-med) var(--ease);
}
/* single-pixel sheen along the top edge — the thing that reads as "glass"
   rather than "translucent panel" */
header::after {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,.16) 22%, rgba(255,255,255,.16) 78%, transparent);
  pointer-events: none;
}
header.scrolled {
  background: rgba(13,17,30,.72);
  border-color: rgba(255,255,255,.08);
  box-shadow: 0 8px 28px -18px rgba(0,0,0,.9);
}
header .wrap { display: flex; align-items: center; gap: 16px; height: 64px; position: relative; }
.brand { display: flex; align-items: center; gap: 10px; font-weight: 650; font-size: 17px; color: var(--text); }
.brand:hover, .brand:focus-visible { text-decoration: none; }
.brand-mark {
  /* the mark is web/logo.svg — the same file the tab icon and the Discord
     avatar are rendered from. It used to be a monospace "</>" typed into a
     gradient box, which meant the header and the favicon were different
     shapes by construction and could never actually match. */
  width: 28px; height: 28px; flex: none; display: block; border-radius: 7px;
  box-shadow: 0 0 0 1px rgba(255,255,255,.10), 0 3px 10px -4px rgba(0,0,0,.7);
}
/* Plain colour, no background-clip:text. The shimmer this replaced was a
   clipped gradient, which renders inconsistently at small sizes and on
   high-DPI displays — it read as a dim or broken wordmark often enough to
   not be worth a hover effect almost nobody sees. Nothing to composite,
   nothing to wash out. */
.brand-text { color: var(--text); }
/* align-items:center, or the links stretch to the nav's full height and their
   text sits above the centre line of the brand and the Sign in button. */
header nav { margin-left: auto; display: flex; align-items: center; gap: 22px; font-size: 14.5px; }
header nav a {
  color: var(--muted); position: relative; padding: 7px 12px; border-radius: 9px;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
/* The hover sweep still runs, inset to the text rather than the padded box so
   it underlines the word and not the pill around it. */
header nav a::after {
  content: ""; position: absolute; left: 12px; right: calc(100% - 12px); bottom: 3px; height: 2px;
  background: var(--accent-2); border-radius: 2px; transition: right var(--dur-med) var(--ease);
}
header nav a:hover, header nav a:focus-visible { color: var(--text); text-decoration: none; }
header nav a:hover::after, header nav a:focus-visible::after { right: 12px; }

/* Account menu. :focus-within opens it for keyboard users, so the items are
   reachable without a pointer. */
.navdrop { position: relative; display: flex; align-items: center; }
.navdrop-top { display: inline-flex; align-items: center; gap: 5px; }
.navchev { width: 11px; height: 11px; transition: transform var(--dur-fast) var(--ease); }
.navdrop:hover .navchev, .navdrop:focus-within .navchev { transform: rotate(180deg); }
/* invisible bridge across the gap to the menu, so moving the pointer down
   doesn't cross un-hovered space and close it */
.navdrop::after { content: ""; position: absolute; top: 100%; left: 0; right: 0; height: 16px; }
.navdrop-menu {
  position: absolute; top: calc(100% + 14px); right: 0; min-width: 200px; z-index: 20;
  display: flex; flex-direction: column; gap: 2px; padding: 7px;
  background: var(--panel); border: 1px solid var(--line); border-radius: 13px;
  box-shadow: var(--shadow-lg, 0 18px 40px rgba(0,0,0,.45));
  opacity: 0; visibility: hidden; transform: translateY(-6px);
  transition: opacity var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease),
              visibility var(--dur-fast) var(--ease);
}
.navdrop:hover .navdrop-menu, .navdrop:focus-within .navdrop-menu {
  opacity: 1; visibility: visible; transform: none;
}
.navdrop-menu a {
  padding: 9px 12px; border-radius: 8px; font-size: 14px; white-space: nowrap;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.navdrop-menu a::after { display: none; }
.navdrop-menu a:hover, .navdrop-menu a:focus-visible { background: var(--panel-2); color: var(--text); }
.navdrop-sep { height: 1px; background: var(--line); margin: 5px 4px; }
/* A button, not a link: signing out is a POST so it can't be fired by a
   third-party <img src="/logout">. Styled to sit flush with the links. */
.navdrop-out {
  display: block; width: 100%; text-align: left; cursor: pointer;
  padding: 9px 12px; border: none; border-radius: 8px; background: none;
  font: inherit; font-size: 14px; color: var(--muted); white-space: nowrap;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.navdrop-out:hover { background: var(--panel-2); color: var(--text); }

/* mobile nav — pure CSS checkbox toggle, no JS needed */
.navtoggle { display: none; }
.navbtn { display: none; }
.navbtn span {
  width: 18px; height: 2px; background: currentColor; border-radius: 2px;
  transition: transform var(--dur-fast) var(--ease), opacity var(--dur-fast) var(--ease);
}
.navtoggle:checked ~ .navbtn span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.navtoggle:checked ~ .navbtn span:nth-child(2) { opacity: 0; }
.navtoggle:checked ~ .navbtn span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

/* hero */
.hero { position: relative; padding: 100px 0 70px; overflow: hidden; }
/* Full-bleed glow: blue from the very top-left of the page, warm out of the
   bottom-right. It used to live inside .hero, which sits in the 1240px wrap
   and clips its overflow — so it could never reach the page edges no matter
   how large the orbs got. Sitting at page level, it spans the real width.

   No blur filter: the orbs are radial gradients that already fade to
   transparent, so blur() only forced a full-viewport layer to re-rasterise
   every frame they moved, at device pixel ratio. Softer stops, same look. */
.page-glow {
  position: absolute; top: 0; left: 0; right: 0; height: 1180px;
  z-index: -1; pointer-events: none; overflow: hidden;
  /* overflow:hidden clips the orbs dead at the bottom edge, which reads as a
     seam across the page. Mask it so the colour dissolves into the background
     instead of stopping at a line. */
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 42%, transparent 96%);
  mask-image: linear-gradient(to bottom, #000 0%, #000 42%, transparent 96%);
}
.orb {
  position: absolute; border-radius: 50%; aspect-ratio: 1;
  will-change: transform;   /* own layer: moving it never repaints the page */
}
.orb-1 {
  width: min(1250px, 88vw); top: -24%; left: -13%;
  background: radial-gradient(circle, rgba(77,124,255,.32) 0%, rgba(77,124,255,.13) 42%, transparent 70%);
  animation: orbFloat1 18s ease-in-out infinite;
}
.orb-2 {
  width: min(1150px, 82vw); bottom: -28%; right: -11%;
  background: radial-gradient(circle, rgba(255,198,61,.17) 0%, rgba(255,198,61,.07) 42%, transparent 70%);
  animation: orbFloat2 21s ease-in-out infinite;
}

/* On a game screen both orbs take that game's colour, so the page's own light
   is a continuation of the card you opened rather than the site's default blue
   sitting behind something orange. The second stays weaker than the first, the
   way the gold one was, or the two cancel into a flat wash. */
.is-playing .orb-1 {
  background: radial-gradient(circle, rgba(var(--play-hue), .30) 0%,
              rgba(var(--play-hue), .12) 42%, transparent 70%);
}
.is-playing .orb-2 {
  background: radial-gradient(circle, rgba(var(--play-hue), .15) 0%,
              rgba(var(--play-hue), .06) 42%, transparent 70%);
}
@keyframes orbFloat1 { 0%,100% { transform: translate(0,0); } 50% { transform: translate(70px,60px); } }
@keyframes orbFloat2 { 0%,100% { transform: translate(0,0); } 50% { transform: translate(-65px,-45px); } }

.hero-grid { display: grid; grid-template-columns: 1.15fr .85fr; gap: 40px; align-items: center; text-align: left; }
.hero h1 {
  font-size: clamp(36px, 5vw, 56px);
  line-height: 1.08; letter-spacing: -.025em; font-weight: 700;
  background: linear-gradient(180deg, #fff, #9fb2e8);
  -webkit-background-clip: text; background-clip: text; color: transparent;
  opacity: 0; animation: heroUp .45s var(--ease) 0s forwards;
}
.hero p.sub {
  font-size: clamp(16px, 1.6vw, 19px); color: var(--muted);
  max-width: 520px; margin: 20px 0 0;
  opacity: 0; animation: heroUp .45s var(--ease) .06s forwards;
}
@keyframes heroUp { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
.cta {
  display: flex; gap: 12px; justify-content: flex-start; margin-top: 34px; flex-wrap: wrap;
  opacity: 0; animation: heroUp .45s var(--ease) .12s forwards;
}
/* Adding the Discord mark to two of these widened the row past the hero
   column and wrapped the guest option onto its own line, orphaning the rule
   next to it. Slightly tighter sides put all three back on one line. */
.hero .cta .btn { padding-inline: 20px; }
.free-note.hero-note {
  opacity: 0; animation: heroUp .45s var(--ease) .18s forwards;
}

/* floating code-card mockup */
.code-card {
  position: relative; background: #0d1020; border: 1px solid var(--line);
  border-radius: 16px; box-shadow: var(--shadow-lg); font-family: ui-monospace, Menlo, monospace;
  animation: cardFloat 6s ease-in-out infinite, heroUp .45s var(--ease) .24s backwards;
}
@keyframes cardFloat { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-10px); } }
.cc-bar { display: flex; align-items: center; gap: 7px; padding: 14px 16px; border-bottom: 1px solid var(--line); }
.cc-bar span:not(.cc-wpm) { width: 11px; height: 11px; border-radius: 50%; background: var(--line); }
.cc-bar span:nth-child(1) { background: #ff5f57; }
.cc-bar span:nth-child(2) { background: #febc2e; }
.cc-bar span:nth-child(3) { background: #28c840; }
.cc-wpm {
  margin-left: auto; font-size: 12px; font-weight: 700; color: var(--accent-2);
  font-family: ui-sans-serif, system-ui, sans-serif; font-variant-numeric: tabular-nums;
}
.cc-body {
  padding: 18px 20px 22px; font-size: 13.5px; line-height: 1.75; white-space: pre-wrap;
  overflow-x: auto; min-height: 148px; cursor: text;
}
.cc-body .untyped { color: var(--muted); }
.cc-body .correct { color: #dbe3ff; }
.cc-body .incorrect { color: #f2777d; background: rgba(237,66,69,.18); border-radius: 2px; }
.cc-body .current { border-left: 2px solid var(--accent-2); animation: caretBlink 1s step-end infinite; margin-left: -2px; }
@keyframes caretBlink { 50% { border-color: transparent; } }
.cc-hint {
  position: absolute; bottom: 14px; right: 20px; font-size: 11px; color: var(--muted);
  opacity: .55; pointer-events: none; transition: opacity var(--dur-med) var(--ease);
  font-family: ui-sans-serif, system-ui, sans-serif;
}
.cc-hint.gone { opacity: 0; }
/* index.html doesn't load app.css (kept lean), so this can't reuse .ty-input —
   same hidden-but-focusable technique, just under its own name here. */
#cc-input { position: absolute; opacity: 0; height: 1px; width: 1px; pointer-events: none; }

@media (max-width: 760px) {
  .hero-grid { grid-template-columns: 1fr; text-align: center; }
  .hero p.sub { margin-left: auto; margin-right: auto; }
  .cta, .cta.hero-cta { justify-content: center; }
  .code-card { max-width: 380px; margin: 8px auto 0; }
}
.btn {
  display: inline-flex; align-items: center; gap: 9px;
  padding: 13px 26px; border-radius: 11px; font-weight: 600; font-size: 15.5px;
  /* <button> doesn't inherit either of these, so a .btn on a form control came
     out in the OS font and ~8px shorter than the same .btn on an <a> next to
     it. Every button/anchor pair on the site was subtly mismatched. */
  font-family: inherit; line-height: 1.65;
  border: 1px solid transparent; cursor: pointer; position: relative; overflow: hidden;
  transition: transform var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease),
              background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.btn::before {
  content: ""; position: absolute; top: 0; left: -60%; width: 40%; height: 100%;
  background: linear-gradient(120deg, transparent, rgba(255,255,255,.22), transparent);
  transform: skewX(-20deg); transition: left var(--dur-slow) var(--ease);
}
.btn:hover::before { left: 130%; }
.btn:hover { transform: translateY(-2px); }
.btn:active { transform: translateY(0) scale(.98); }
.btn-primary { background: var(--accent); color: #fff; box-shadow: 0 1px 0 rgba(255,255,255,.15) inset, var(--shadow-sm); }
.btn-primary:hover { background: #3d6bee; text-decoration: none; box-shadow: 0 1px 0 rgba(255,255,255,.15) inset, var(--glow); }
.btn-ghost { border-color: var(--line); color: var(--text); background: var(--panel); }
.btn-ghost:hover { border-color: #33406a; text-decoration: none; box-shadow: var(--shadow-sm); }
.free-note { margin-top: 16px; font-size: 13.5px; color: var(--muted); }

/* stats */
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px,1fr)); gap: 14px; margin: 8px 0 72px; }
.stat {
  background: var(--panel); border: 1px solid var(--line); border-radius: 14px; padding: 22px 18px; text-align: center;
  transition: transform var(--dur-med) var(--ease), box-shadow var(--dur-med) var(--ease), border-color var(--dur-med) var(--ease);
}
.stat:hover { transform: translateY(-4px); border-color: #33406a; box-shadow: var(--shadow-md); }
.stat .n { font-size: 34px; font-weight: 700; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.stat .l { font-size: 12.5px; color: var(--muted); text-transform: uppercase; letter-spacing: .07em; margin-top: 4px; }

/* sections */
section { padding: 26px 0 72px; }
h2 { font-size: 27px; letter-spacing: -.02em; margin-bottom: 8px; font-weight: 650; }
.section-sub { color: var(--muted); margin-bottom: 28px; }

.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(270px,1fr)); gap: 16px; }
.card {
  background: var(--panel); border: 1px solid var(--line); border-radius: 14px; padding: 22px;
  transition: transform var(--dur-med) var(--ease), box-shadow var(--dur-med) var(--ease), border-color var(--dur-med) var(--ease);
}
.card:hover { transform: translateY(-4px); border-color: #33406a; box-shadow: var(--shadow-md); }
.card h3 { font-size: 16.5px; margin-bottom: 7px; font-weight: 620; }
.card p { color: var(--muted); font-size: 14.5px; }
.card .ic {
  width: 44px; height: 44px; border-radius: 12px; margin-bottom: 14px;
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(140deg, rgba(77,124,255,.18), rgba(77,124,255,.05));
  border: 1px solid rgba(77,124,255,.25); color: var(--accent-2);
  transition: transform var(--dur-med) var(--ease);
}
.card .ic svg { width: 22px; height: 22px; }
.card:hover .ic { transform: scale(1.08) rotate(-4deg); }

.langs { display: flex; flex-wrap: wrap; gap: 9px; }
.lang {
  background: var(--panel-2); border: 1px solid var(--line); color: var(--text);
  padding: 8px 15px; border-radius: 999px; font-size: 14px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  display: inline-block; transition: transform var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}
.lang:hover { transform: translateY(-3px); border-color: var(--accent-2); box-shadow: var(--shadow-sm); }

/* command table */
.cmds { background: var(--panel); border: 1px solid var(--line); border-radius: 14px; overflow: hidden; }
.cmd { display: flex; gap: 18px; padding: 14px 20px; border-bottom: 1px solid var(--line); font-size: 14.5px; transition: background var(--dur-fast) var(--ease); }
.cmd:last-child { border-bottom: none; }
.cmd:hover { background: var(--panel-2); }
.cmd code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  color: var(--accent-2); font-size: 14px; min-width: 150px; flex: none;
}
.cmd span { color: var(--muted); }

/* doc pages */
.doc { padding: 52px 0 90px; max-width: 780px; }
.doc h1 { font-size: 36px; letter-spacing: -.02em; margin-bottom: 6px; }
.doc .updated { color: var(--muted); font-size: 14px; margin-bottom: 36px; }
.doc h2 { font-size: 21px; margin: 38px 0 10px; }
.doc p, .doc li { color: #c3cbe4; font-size: 15.5px; }
.doc ul { margin: 12px 0 12px 22px; }
.doc li { margin-bottom: 7px; }
.doc table { width: 100%; border-collapse: collapse; margin: 18px 0; font-size: 14.5px; }
.doc th, .doc td { text-align: left; padding: 11px 14px; border-bottom: 1px solid var(--line); }
.doc th { color: var(--text); font-weight: 620; background: var(--panel); }
.doc td { color: var(--muted); }
.doc strong { color: var(--text); }
.doc code { font-family: ui-monospace, Menlo, monospace; background: var(--panel-2); padding: 2px 6px; border-radius: 5px; font-size: 14px; }

/* closing CTA spotlight */
.cta-panel {
  position: relative; overflow: hidden; text-align: center;
  background: linear-gradient(160deg, var(--panel), var(--panel-2));
  border: 1px solid var(--line); border-radius: 20px; padding: 60px 32px;
}
.cta-panel::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(600px circle at 50% 0%, rgba(77,124,255,.16), transparent 60%);
}
.cta-panel > * { position: relative; }

footer { border-top: 1px solid var(--line); padding: 30px 0; color: var(--muted); font-size: 14px; }
footer .wrap { display: flex; gap: 20px; flex-wrap: wrap; align-items: center; }
footer nav { margin-left: auto; display: flex; gap: 20px; }

@media (max-width: 620px) {
  .hero { padding: 60px 0 44px; }
  .cmd { flex-direction: column; gap: 3px; }
  .cmd code { min-width: 0; }

  .navbtn {
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px;
    margin-left: auto; width: 36px; height: 36px; border-radius: 8px;
    border: 1px solid var(--line); background: var(--panel); color: var(--text);
    cursor: pointer; user-select: none; transition: border-color var(--dur-fast) var(--ease);
  }
  .navtoggle:checked ~ .navbtn { border-color: var(--accent); }
  header nav {
    margin-left: 0; gap: 0; font-size: 15px;
    position: absolute; top: 100%; left: 0; right: 0;
    flex-direction: column; align-items: stretch;
    background: var(--bg); border-bottom: 1px solid var(--line);
    max-height: 0; overflow: hidden; transition: max-height var(--dur-med) var(--ease);
  }
  header nav a { padding: 14px 24px; border-top: 1px solid var(--line); }
  header nav a::after { display: none; }
  .navtoggle:checked ~ nav { max-height: 60vh; overflow-y: auto; }

  /* no hover on touch — the menu just becomes part of the stacked nav */
  .navdrop { position: static; display: block; }
  .navdrop::after { display: none; }
  .navchev { display: none; }
  .navdrop-menu {
    position: static; opacity: 1; visibility: visible; transform: none;
    display: block; background: none; border: none; box-shadow: none;
    padding: 0; min-width: 0; border-radius: 0;
  }
  .navdrop-menu a { padding-left: 42px; border-radius: 0; font-size: 14px; color: var(--muted); }
  .navdrop-sep { display: none; }
}



/* No opacity animation on <body> or the header. It looked harmless, but an
   animation with fill-mode keeps applying opacity after it finishes, which
   holds the element in a composited layer — and background-clip:text gradients
   inside an opacity layer render washed out. That's what greyed the headline
   and the brand mark on every load. The hero's own entrance is enough. */

/* Header control depends on who you are, chosen from the cq_state hint cookie
   by an inline script in <head> so it's settled before first paint. A guest
   should never see an "Account" menu for an account they don't have. */
[data-when] { display: none !important; }
html.is-user  [data-when="user"]  { display: flex !important; }
html.is-guest [data-when="guest"] { display: inline-flex !important; }
/* "anon" is anyone without a real account — a visitor or a guest. Without it a
   [data-when] link would vanish for visitors, who match no is-* rule. */
html.is-visitor [data-when="anon"], html.is-guest [data-when="anon"] { display: inline-flex !important; }

.navsignin, .navsignin-cta {
  display: inline-flex; align-items: center; padding: 7px 16px; border-radius: 9px;
  background: var(--accent); color: #fff; font-weight: 600; font-size: 14px;
  transition: background var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
.navsignin:hover, .navsignin-cta:hover { background: #3d6bee; text-decoration: none; transform: translateY(-1px); }
.navsignin::after, .navsignin-cta::after { display: none; }

/* Guests get one clear prompt where a signed-in player's progress would be,
   instead of a dashboard full of zeroes that will never fill in. */
.signin-prompt {
  display: flex; align-items: center; justify-content: space-between; gap: 24px;
  flex-wrap: wrap; padding: 30px 32px; margin-bottom: 40px; border-radius: 16px;
  background: linear-gradient(140deg, rgba(77,124,255,.14), rgba(77,124,255,.04));
  border: 1px solid rgba(77,124,255,.28);
}
.signin-prompt h2 { font-size: 22px; margin-bottom: 6px; }
.signin-prompt p  { color: var(--muted); font-size: 15px; max-width: 60ch; }

/* ---------- landing demos ---------- */
/* Mock-ups rather than screenshots: they stay sharp at any size, restyle with
   the theme, and never go stale when the real UI changes underneath them. */

/* Discord */
.dc-window {
  position: relative;              /* the submit modal is scoped to the window */
  background: #313338; border: 1px solid #232428; border-radius: 14px;
  overflow: hidden; box-shadow: var(--shadow-lg); max-width: 720px;
  /* Centred, and the commands now live outside it — so the whole window is
     conversation rather than 240px of permanent picker chrome. */
  display: flex; flex-direction: column;
  margin-inline: auto; text-align: left;
}
.dc-head {
  display: flex; align-items: center;
  background: #2b2d31; padding: 12px 18px; font-size: 14.5px; font-weight: 600;
  color: #f2f3f5; border-bottom: 1px solid #232428;
}
.dc-hash { color: #80848e; margin-right: 4px; }
.dc-headnote {
  margin-left: auto; font-size: 11px; font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; color: #949ba4;
  border: 1px solid #4e5058; border-radius: 4px; padding: 2px 7px;
}

/* Takes whatever the capped window has left over. Bounded either way, so
   running a command still doesn't shunt the rest of the page around, and the
   channel still reads as a window into something bigger. */
.dc-scroll {
  flex: none; height: 300px; overflow-y: auto; padding: 8px 0;
  scrollbar-width: thin; scrollbar-color: #1e1f22 transparent;
  scroll-behavior: smooth;
}
.dc-scroll::-webkit-scrollbar { width: 8px; }
.dc-scroll::-webkit-scrollbar-thumb { background: #1e1f22; border-radius: 4px; }
.dc-empty {
  height: 100%; display: grid; place-items: center;
  color: #949ba4; font-size: 14px; padding: 0 24px; text-align: center;
}
.dc-msg { display: flex; gap: 14px; padding: 14px 18px; }
.dc-msg + .dc-msg { padding-top: 4px; }
.dc-av {
  width: 40px; height: 40px; border-radius: 50%; flex: none;
  background: #5865f2; color: #fff; display: grid; place-items: center;
  font-weight: 700; font-size: 15px;
}
.dc-av.bot { background: none; }
.dc-av.bot img { width: 40px; height: 40px; border-radius: 50%; }
.dc-body { min-width: 0; }
.dc-name { font-size: 14.5px; font-weight: 600; color: #f2f3f5; margin-bottom: 3px; }
.dc-bot {
  background: #5865f2; color: #fff; font-size: 10px; font-weight: 600;
  padding: 1px 5px; border-radius: 4px; vertical-align: 1px; letter-spacing: .02em;
}
.dc-time { color: #949ba4; font-size: 12px; font-weight: 400; margin-left: 6px; }
.dc-slash { color: #dbdee1; font-size: 14.5px; }
.dc-slash span { color: #949bf3; background: rgba(88,101,242,.15); padding: 1px 4px; border-radius: 3px; }
.dc-slash em { color: #949bf3; font-style: normal; }
.dc-embed {
  border-left: 4px solid var(--accent); background: #2b2d31;
  border-radius: 4px; padding: 14px 16px; max-width: 460px; margin-top: 4px;
}
.dc-embed-top { color: #b5bac1; font-size: 12.5px; margin-bottom: 7px; }
.dc-embed-q { color: #f2f3f5; font-size: 15.5px; font-weight: 600; margin-bottom: 11px; }
.dc-embed-q code { background: #1e1f22; padding: 1px 5px; border-radius: 4px; font-size: 14px; }
.dc-embed-body { color: #dbdee1; font-size: 14px; line-height: 1.55; margin-bottom: 10px; }
.dc-embed-pre {
  background: #1e1f22; border-radius: 4px; padding: 9px 12px;
  font-family: ui-monospace, Menlo, monospace; font-size: 12.5px; color: #b9c6e8;
  overflow-x: auto; white-space: pre-wrap;
}
.dc-buttons { display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
.dc-buttons button {
  background: #4e5058; color: #fff; font-size: 13.5px; font-weight: 500;
  padding: 7px 15px; border: none; border-radius: 4px; cursor: pointer;
  font-family: inherit; transition: background var(--dur-fast) var(--ease), opacity var(--dur-fast) var(--ease);
}
.dc-buttons button:hover:not(:disabled) { background: #6d6f78; }
.dc-buttons .ghost { background: none; border: 1px solid #4e5058; color: #b5bac1; }
.dc-buttons .ghost:hover:not(:disabled) { background: #4e5058; color: #fff; }
/* Spent buttons stay legible — Discord greys them out but leaves them readable,
   and the marked-up right/wrong answer is the whole point of the reply. */
.dc-buttons button:disabled { cursor: default; opacity: .65; }
.dc-buttons button.right { background: #23a55a; opacity: 1; }
.dc-buttons button.wrong { background: #da373c; opacity: 1; }

.dc-thinking {
  display: flex; align-items: center; gap: 5px;
  padding: 6px 18px 10px 72px; color: #949ba4; font-size: 13.5px;
}
.dc-thinking span {
  width: 5px; height: 5px; border-radius: 50%; background: #949ba4;
  animation: dcDot 1.1s infinite ease-in-out;
}
.dc-thinking span:nth-child(2) { animation-delay: .16s; }
.dc-thinking span:nth-child(3) { animation-delay: .32s; margin-right: 5px; }
@keyframes dcDot { 0%, 60%, 100% { opacity: .25; } 30% { opacity: 1; } }

.dc-ephemeral {
  margin: 2px 18px 10px 72px; padding: 10px 14px; border-radius: 4px;
  background: #2b2d31; border-left: 4px solid #4e5058;
  color: #dbdee1; font-size: 14px; line-height: 1.5; max-width: 460px;
}
.dc-onlyyou { display: block; margin-top: 6px; color: #949ba4; font-size: 12px; }

.dc-verdict {
  font-size: 14.5px; border-radius: 4px; padding: 11px 15px;
  margin-top: 4px; max-width: 460px;
}
.dc-verdict.good { color: #23a55a; background: rgba(35,165,90,.1); border-left: 4px solid #23a55a; }
.dc-verdict.bad  { color: #f0787c; background: rgba(218,55,60,.1);  border-left: 4px solid #da373c; }
.dc-verdict.good strong { color: #2dd06e; }
.dc-verdict.bad strong { color: #ff9a9d; }
.dc-why {
  color: #b5bac1; font-size: 13.5px; line-height: 1.55;
  margin-top: 8px; max-width: 460px;
}
.dc-why code { background: #1e1f22; padding: 1px 5px; border-radius: 4px; font-size: 12.5px; }

.dc-tests { margin-top: 8px; max-width: 460px; display: grid; gap: 4px; }
.dc-tests .t {
  font-family: ui-monospace, Menlo, monospace; font-size: 12.5px;
  color: #b5bac1; padding-left: 20px; position: relative;
}
.dc-tests .t::before { position: absolute; left: 0; font-family: inherit; }
.dc-tests .pass::before { content: "✓"; color: #23a55a; }
.dc-tests .fail::before { content: "✕"; color: #da373c; }

.dc-submitted { margin-top: 4px; max-width: 460px; }
.dc-submitted pre {
  background: #1e1f22; border-radius: 4px; padding: 10px 13px;
  font-family: ui-monospace, Menlo, monospace; font-size: 12.5px;
  color: #b9c6e8; overflow-x: auto; line-height: 1.6;
}

/* /rank */
/* Discord lays inline fields out in a row of three, each with a bold grey
   name above its value. */
.dc-fields { display: flex; gap: 34px; flex-wrap: wrap; margin-top: 12px; }
.dc-fields div { color: #dbdee1; font-size: 14px; }
.dc-fields b { display: block; color: #f2f3f5; font-size: 13px; font-weight: 700; margin-bottom: 1px; }
.dc-field-block { margin-top: 12px; color: #dbdee1; font-size: 13.5px; line-height: 1.6; }
.dc-field-block b { display: block; color: #f2f3f5; font-size: 13px; font-weight: 700; margin-bottom: 2px; }
.dc-field-block code { background: #1e1f22; padding: 1px 5px; border-radius: 4px; font-size: 12.5px; }
.dc-author { display: flex; align-items: center; gap: 8px; color: #f2f3f5; font-size: 13.5px; font-weight: 600; margin-bottom: 8px; }
.dc-authoravatar {
  width: 22px; height: 22px; border-radius: 50%; background: #5865f2; color: #fff;
  display: grid; place-items: center; font-size: 11px; font-weight: 700;
}
.dc-embed-desc { color: #dbdee1; font-size: 14px; line-height: 1.6; }
.dc-bar { font-family: ui-monospace, Menlo, monospace; color: #5865f2; letter-spacing: -1px; }

/* /leaderboard is a description made of lines, not a table — matching the bot */
.dc-lb > div { padding: 2px 0; }
.dc-lb strong { color: #f2f3f5; }
.dc-lb em { color: #b5bac1; font-style: italic; }
.dc-medal { display: inline-block; width: 22px; }
.dc-mono {
  font-family: ui-monospace, Menlo, monospace; font-size: 12.5px;
  background: #1e1f22; padding: 1px 5px; border-radius: 4px; color: #b9c6e8;
}

/* the language dropdown the challenge view shows above its buttons — a select
   menu is its own action row, full width, not a pill beside the button */
.dc-select {
  display: flex; align-items: center; justify-content: space-between;
  margin-top: 10px; max-width: 460px;
  background: #1e1f22; border: 1px solid #4e5058; border-radius: 4px;
  padding: 10px 14px; color: #dbdee1; font-size: 14px;
}
.dc-select svg { width: 13px; height: 13px; color: #949ba4; }

/* Discord prints "Name used /command" as a small hooked line above the reply,
   rather than posting your command as a message of its own. */
.dc-used {
  display: flex; align-items: center; gap: 6px;
  padding: 10px 18px 2px 40px; position: relative;
  color: #949ba4; font-size: 13px;
}
.dc-hook {
  position: absolute; left: 22px; top: 15px; width: 26px; height: 11px;
  border-left: 2px solid #4e5058; border-top: 2px solid #4e5058;
  border-top-left-radius: 6px;
}
.dc-usedav {
  width: 16px; height: 16px; border-radius: 50%; background: #5865f2; color: #fff;
  display: grid; place-items: center; font-size: 9px; font-weight: 700;
}
.dc-usedname { color: #dbdee1; font-weight: 600; }
.dc-usedcmd { color: #949bf3; background: rgba(88,101,242,.15); padding: 1px 5px; border-radius: 3px; }
.dc-usedcmd::before { content: "/"; }

.dc-expected {
  background: #1e1f22; border: 1px solid #2b2d31; border-radius: 4px;
  padding: 9px 13px; margin: 6px 0 4px; max-width: 440px;
  font-family: ui-monospace, Menlo, monospace; font-size: 13px; color: #b9c6e8;
}

/* Discord's slash-command picker: a panel that opens above the message box
   once you type "/", one row per command with its description and the app it
   belongs to. Standing open here because it's the menu, not a decoration. */
.dc-composer { flex: none; background: #2b2d31; border-top: 1px solid #232428; padding: 0 0 12px; }
.dc-cmdrow {
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 8px 16px; border: none; background: none; cursor: pointer;
  text-align: left; font-family: inherit;
  transition: background var(--dur-fast) var(--ease);
}
.dc-cmdrow:hover { background: #35373c; }
.dc-cmdicon { border-radius: 6px; flex: none; }
.dc-cmdmain { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.dc-cmdmain b { color: #f2f3f5; font-size: 14.5px; font-weight: 600; }
.dc-cmdmain span { color: #b5bac1; font-size: 13px; }

.dc-inputbar {
  display: flex; align-items: center; gap: 14px;
  margin: 12px 16px 0; padding: 11px 16px;
  background: #383a40; border-radius: 8px;
}
.dc-plus {
  width: 22px; height: 22px; flex: none; border-radius: 50%; background: #b5bac1;
  color: #383a40; display: grid; place-items: center; font-size: 16px; font-weight: 400;
  line-height: 1;
}
.dc-inputtext { color: #dbdee1; font-size: 15px; }
/* the caret that says this is a live input, not a picture of one */
.dc-inputtext::after {
  content: ""; display: inline-block; width: 1px; height: 15px;
  background: #dbdee1; margin-left: 1px; vertical-align: -2px;
  animation: dcCaret 1.1s steps(1) infinite;
}
@keyframes dcCaret { 0%, 50% { opacity: 1; } 51%, 100% { opacity: 0; } }

/* the code-submission modal */
.dc-modal {
  position: absolute; inset: 0; z-index: 3;
  background: rgba(0,0,0,.6); display: grid; place-items: center; padding: 20px;
}
.dc-modal[hidden] { display: none; }
.dc-modal-card {
  width: 100%; max-width: 440px; background: #313338;
  border-radius: 8px; padding: 20px; box-shadow: var(--shadow-lg);
}
.dc-modal-title { color: #f2f3f5; font-size: 17px; font-weight: 700; margin-bottom: 14px; }
.dc-modal-label {
  color: #b5bac1; font-size: 11px; font-weight: 700;
  letter-spacing: .04em; text-transform: uppercase; margin-bottom: 7px;
}
.dc-modal-code {
  width: 100%; height: 108px; resize: none;
  background: #1e1f22; border: 1px solid #1e1f22; border-radius: 4px;
  color: #dbe3f7; padding: 11px 13px;
  font-family: ui-monospace, Menlo, monospace; font-size: 13px; line-height: 1.6;
}
.dc-modal-code:focus { outline: none; border-color: var(--accent); }
.dc-modal-foot { display: flex; justify-content: flex-end; gap: 10px; margin-top: 18px; }
.dc-modal-cancel, .dc-modal-go {
  font-family: inherit; font-size: 14px; font-weight: 500;
  padding: 9px 17px; border-radius: 4px; border: none; cursor: pointer;
}
.dc-modal-cancel { background: none; color: #dbdee1; }
.dc-modal-cancel:hover { text-decoration: underline; }
.dc-modal-go { background: #5865f2; color: #fff; }
.dc-modal-go:hover { background: #4752c4; }

.dc-cta {
  display: flex; align-items: center; justify-content: center; gap: 18px; flex-wrap: wrap;
  max-width: 720px; margin: 22px auto 0; text-align: center;
}

/* The demo is a showcase, so the whole block is centred on the page. */
#demo-discord > h2, #demo-discord > .section-sub { text-align: center; }
#demo-discord > .section-sub { max-width: 720px; margin-inline: auto; }

/* Commands as controls under the window: a two-up grid of real buttons that
   read as chrome for the demo rather than part of the Discord client. */
.dc-controls {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px;
  max-width: 720px; margin: 18px auto 0;
}
.dc-controls .dc-cmdrow {
  border: 1px solid var(--line); border-radius: 11px;
  background: var(--panel); padding: 11px 14px; gap: 11px;
}
.dc-controls .dc-cmdrow:hover { background: var(--panel-2); border-color: rgba(77,124,255,.45); }
.dc-controls.busy { opacity: .55; pointer-events: none; }
@media (max-width: 620px) { .dc-controls { grid-template-columns: 1fr; } }

/* Learn */
.ln-demo {
  background: var(--panel); border: 1px solid var(--line); border-radius: 16px;
  padding: 28px 32px; max-width: 720px; box-shadow: var(--shadow-md);
}
.ln-meta { color: var(--muted); font-size: 13px; letter-spacing: .04em; text-transform: uppercase; }
.ln-title { font-size: 27px; letter-spacing: -.02em; margin: 6px 0 12px; }
.ln-body { color: #c3cbe4; font-size: 15.5px; margin-bottom: 22px; }
.ln-body code, .ln-prompt code {
  background: var(--panel-2); padding: 1px 6px; border-radius: 5px;
  font-family: ui-monospace, Menlo, monospace; font-size: 14px;
}
.ln-eglabel {
  font-size: 11.5px; text-transform: uppercase; letter-spacing: .08em;
  color: var(--accent-2); font-weight: 600; margin-bottom: 8px;
}
.ln-prompt { font-size: 15.5px; margin-bottom: 14px; }
.ln-editor {
  display: flex; background: #0c1020; border: 1px solid var(--line);
  border-radius: 10px; overflow: hidden; font-family: ui-monospace, Menlo, monospace;
}
.ln-gutter {
  display: flex; flex-direction: column; padding: 14px 12px; gap: 4px;
  background: rgba(255,255,255,.02); color: #4a5578; font-size: 13.5px; text-align: right;
}
.ln-code { padding: 14px 16px; font-size: 13.5px; line-height: 1.72; color: #dbe3f7; }
.ln-code .k  { color: #7aa2ff; }
.ln-code .s  { color: #7ddba4; }
.ln-code .fn { color: #ffc63d; }
.ln-verdict {
  margin-top: 16px; color: var(--green); font-size: 15px;
  background: rgba(74,222,128,.1); border: 1px solid rgba(74,222,128,.25);
  border-radius: 10px; padding: 12px 16px;
}

@media (max-width: 620px) {
  .dc-msg { padding: 12px; gap: 10px; }
  .ln-demo { padding: 22px 18px; }
}

/* ---------- sign-in page ---------- */
/* Deliberately one narrow column with nothing else on the page: this is a
   decision point, and every extra link is a way to leave without making it. */
.signin-page {
  min-height: calc(100vh - 220px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 60px 0 90px;
}
.signin-card {
  width: 100%;
  max-width: 460px;
  text-align: center;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 20px;
  padding: 44px 40px 36px;
  box-shadow: var(--shadow-lg);
}
.signin-mark { display: block; margin: 0 auto 20px; border-radius: 13px; }
.signin-card h1 { font-size: 30px; letter-spacing: -.02em; margin-bottom: 12px; }
.signin-card .section-sub { font-size: 15px; margin-bottom: 28px; }

.signin-discord {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  padding: 14px 20px;
  font-size: 16px;
}
.signin-discord svg { flex: none; }

.signin-perks { list-style: none; margin: 24px 0 0; text-align: left; }
.signin-perks li {
  position: relative;
  padding: 0 0 0 26px;
  margin-bottom: 10px;
  color: var(--muted);
  font-size: 14px;
  line-height: 1.5;
}
.signin-perks li::before {
  content: "";
  position: absolute;
  left: 4px; top: 7px;
  width: 9px; height: 5px;
  border-left: 2px solid var(--green);
  border-bottom: 2px solid var(--green);
  transform: rotate(-45deg);
}

.signin-sep {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 28px 0 22px;
  color: var(--muted);
  font-size: 13px;
}
.signin-sep::before, .signin-sep::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--line);
}

.signin-guest { width: 100%; }
.signin-note {
  color: var(--muted);
  font-size: 13px;
  line-height: 1.5;
  margin-top: 14px;
}
.signin-legal {
  color: var(--muted);
  font-size: 12.5px;
  margin-top: 28px;
  padding-top: 20px;
  border-top: 1px solid var(--line);
}

@media (max-width: 520px) {
  .signin-card { padding: 34px 24px 28px; }
  .signin-card h1 { font-size: 25px; }
}
.signin-server {
  margin-top: 22px;
  padding-top: 20px;
  border-top: 1px solid var(--line);
}

/* Matches the real embed: bold title, bold question as the description, small
   grey footer. Options live on the buttons, which is where the bot puts them. */
.dc-embed-title { color: #f2f3f5; font-size: 15.5px; font-weight: 700; margin-bottom: 7px; }
.dc-embed-foot { color: #949ba4; font-size: 11.5px; margin-top: 10px; }
/* A view's buttons live in one action row of up to five, so they sit
   side by side however long the labels are. */
.dc-buttons.row { flex-wrap: nowrap; max-width: 100%; }
.dc-buttons.row button { flex: 1 1 0; min-width: 0; }
.dc-buttons button.green { background: #248046; display: inline-flex; align-items: center; gap: 7px; }
.dc-buttons button.green:hover:not(:disabled) { background: #1a6334; }
.dc-buttons + .dc-buttons { margin-top: 8px; }
.dc-verdict b, .dc-verdict strong { font-weight: 700; }
.dc-ephemeral b { color: #f2f3f5; }

/* The guest option isn't a third equal choice — it's the way past the other
   two. Same footprint as the ghost button so the row stays even, but grey and
   unfilled, with a rule marking it off from the two real actions. */
.cta-sep {
  width: 1px; align-self: stretch; margin: 4px 6px;
  background: rgba(255,255,255,.13); flex: none;
}
.btn-quiet {
  background: none; border-color: transparent; color: var(--muted);
}
/* No fill on hover — it stays a bare label. The .btn shine sweep and the text
   brightening are the whole hover state, which is what keeps it reading as
   the quiet way past the two real buttons rather than a third one. */
.btn-quiet:hover { color: var(--text); background: none; text-decoration: none; }

/* Sits under the primary Discord button as a second, equal-weight option. */
.signin-alt { width: 100%; justify-content: center; margin-top: 10px; }
.signin-alt svg { flex: none; }

.linked-tag {
  font-size: 12.5px; font-weight: 600; letter-spacing: .02em;
  color: var(--green); border: 1px solid rgba(74,222,128,.32);
  border-radius: 999px; padding: 4px 12px; white-space: nowrap;
}

/* Adding the bot is the second-most-likely reason someone is here, and it
   needs no account — so it's reachable from the nav rather than only from
   halfway down the page. A link, not a button: Sign in stays the one button. */
.nav-invite { white-space: nowrap; }
