/* Geist, because the system stack was the one thing making the dashboard read
   as a web page rather than an application. An @import rather than a link tag
   in eleven HTML files: one place to change, and the CSP below is widened to
   match. */
@import url('https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600;700&family=Inter:wght@400;500;600;700&display=swap');

:root {
  /* Darker than it was. The surfaces used to sit close enough to the page that
     every panel read as a slightly lighter rectangle floating on grey; pulling
     the ground down and the panels with it lets the accent and the text do the
     separating instead of a wash of near-black tones competing. */
  --bg: #050506;
  --panel: rgba(255, 255, 255, .022);
  --panel-solid: #0A090C;
  --sakura: #F7B7CB;
  --cream: #FFE3B8;
  --teal: #7FD1C4;
  --plum: #B3A4C8;
  --panel2: #100E14;
  --line: #1A181F;
  --line-hi: #262230;
  --text: #ffffff;
  --muted: #9b9ba4;
  --dim: #6a6a74;
  --accent: #B3A4C8;
  --green: #6ee7a8;
  --amber: #fbbf24;
  --red: #f87171;
  --discord: #5865F2;
  --r-card: 14px;
  --shadow: rgba(0, 0, 0, .65) 0 0 30px 6px;
}

* { box-sizing: border-box; }

/* Casual drag-select deterrent. Inputs, code samples and anything explicitly
   marked stay selectable, because breaking copy for real use is worse than the
   copying it prevents. */
body { -webkit-user-select: none; -moz-user-select: none; user-select: none; }
input, textarea, select, code, pre, .selectable, [contenteditable] {
  -webkit-user-select: text; -moz-user-select: text; user-select: text;
}
img { -webkit-user-drag: none; user-drag: none; }
html { color-scheme: dark; scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  min-height: 100vh;
  font: 16px/1.65 Geist, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  letter-spacing: -.011em;
  -webkit-font-smoothing: antialiased;
  position: relative;
  overflow-x: hidden;
}

body::before {
  content: "";
  position: fixed;
  inset: 0;
  background:
    radial-gradient(1000px 680px at 50% -14%, rgba(247,183,203,.15), transparent 64%),
    radial-gradient(760px 560px at 6% 18%, rgba(255,227,184,.09), transparent 62%),
    radial-gradient(820px 600px at 96% 34%, rgba(127,209,196,.08), transparent 62%),
    radial-gradient(900px 700px at 30% 78%, rgba(179,164,200,.10), transparent 66%),
    linear-gradient(180deg, rgba(28,18,26,.55), transparent 30%);
  pointer-events: none;
  z-index: 0;
}

/* A slow colour field. No motifs - just the palette moving, which reads as
   depth without putting objects on the page. */
body .petals {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background:
    radial-gradient(46vw 46vw at 18% 26%, rgba(247,183,203,.20), transparent 58%),
    radial-gradient(40vw 40vw at 82% 18%, rgba(127,209,196,.16), transparent 58%),
    radial-gradient(52vw 52vw at 62% 84%, rgba(179,164,200,.20), transparent 60%),
    radial-gradient(36vw 36vw at 8% 78%, rgba(255,227,184,.13), transparent 58%),
    radial-gradient(30vw 30vw at 95% 68%, rgba(88,101,242,.13), transparent 60%);
  animation: fieldDrift 48s var(--ease) infinite alternate;
}

/* A faint rule grid, masked to fade out from the middle. Gives the page a
   floor to sit on without drawing anything the eye has to read. */
body .grid-layer {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  opacity: .5;
  background-image:
    linear-gradient(rgba(255,255,255,.028) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.028) 1px, transparent 1px);
  background-size: 64px 64px;
  -webkit-mask-image: radial-gradient(120vw 90vh at 50% 26%, #000 8%, transparent 72%);
  mask-image: radial-gradient(120vw 90vh at 50% 26%, #000 8%, transparent 72%);
}

/* Soft glow bands that sit behind content and give the long scroll some
   rhythm rather than one flat field the whole way down. */
body .glow-layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background:
    radial-gradient(60vw 460px at 12% 34%, rgba(247,183,203,.07), transparent 68%),
    radial-gradient(56vw 420px at 88% 52%, rgba(127,209,196,.06), transparent 68%),
    radial-gradient(64vw 500px at 30% 72%, rgba(179,164,200,.07), transparent 68%),
    radial-gradient(52vw 400px at 76% 88%, rgba(255,227,184,.05), transparent 68%);
}

@keyframes fieldDrift {
  from { transform: translate3d(-1.5%, -1%, 0) scale(1.04); }
  to   { transform: translate3d(1.5%, 1.5%, 0) scale(1.1); }
}

/* Fine grain over the top so the gradients do not band on wide screens. */
body .petals::after {
  content: "";
  position: absolute;
  inset: 0;
  opacity: .5;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2'/><feColorMatrix type='saturate' values='0'/></filter><rect width='140' height='140' filter='url(%23n)' opacity='.045'/></svg>");
}

body::after {
  content: "";
  position: fixed;
  inset: -60px;
  pointer-events: none;
  z-index: 0;
  opacity: .6;
  background-image:
    radial-gradient(1.4px 1.4px at 12% 18%, rgba(255,255,255,.85), transparent),
    radial-gradient(1.1px 1.1px at 27% 62%, rgba(255,255,255,.6), transparent),
    radial-gradient(1.6px 1.6px at 41% 31%, rgba(179,164,200,.9), transparent),
    radial-gradient(1px 1px at 56% 74%, rgba(255,255,255,.55), transparent),
    radial-gradient(1.5px 1.5px at 68% 21%, rgba(255,255,255,.75), transparent),
    radial-gradient(1.2px 1.2px at 79% 58%, rgba(179,164,200,.8), transparent),
    radial-gradient(1px 1px at 91% 36%, rgba(255,255,255,.6), transparent),
    radial-gradient(1.3px 1.3px at 5% 82%, rgba(255,255,255,.5), transparent),
    radial-gradient(1.1px 1.1px at 34% 92%, rgba(179,164,200,.7), transparent),
    radial-gradient(1.4px 1.4px at 62% 8%, rgba(255,255,255,.7), transparent);
  background-size: 100% 100%;
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: none; }

/* ---------- motion ----------
   One easing curve everywhere so the whole site feels like one thing.
   Everything here is disabled wholesale by the reduced-motion block at the
   bottom of this file. */

:root { --ease: cubic-bezier(.22, .61, .36, 1); }

@keyframes fadeUp {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: none; }
}
@keyframes fadeDown {
  from { opacity: 0; transform: translateY(-12px); }
  to   { opacity: 1; transform: none; }
}
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes popIn {
  0%   { opacity: 0; transform: scale(.9); }
  60%  { transform: scale(1.02); }
  100% { opacity: 1; transform: scale(1); }
}
@keyframes shimmer {
  from { background-position: -200% 0; }
  to   { background-position: 200% 0; }
}
/* A live indicator should look alive. */
@keyframes pulse {
  0%, 100% { box-shadow: 0 0 0 3px rgba(110,231,168,.15); }
  50%      { box-shadow: 0 0 0 6px rgba(110,231,168,.05); }
}

.anim { opacity: 0; animation: fadeUp .55s var(--ease) forwards; }
.anim-in { opacity: 0; animation: fadeIn .5s var(--ease) forwards; }
.anim-pop { opacity: 0; animation: popIn .45s var(--ease) forwards; }

/* Stagger, so groups cascade instead of arriving as a slab. */
/* Settings sit as separate rectangles side by side rather than one long
   column, so a wide screen shows several at once and each reads as its own
   thing rather than a section of one big panel. */
.stagger {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(330px, 1fr));
  gap: 1rem;
  align-items: start;
}
.stagger > .sgroup { margin-bottom: 0; }
.stagger > p { grid-column: 1 / -1; }

@media (max-width: 720px) {
  .stagger { grid-template-columns: 1fr; }
}

.stagger > * { opacity: 0; animation: fadeUp .5s var(--ease) forwards; }
.stagger > *:nth-child(1) { animation-delay: .04s; }
.stagger > *:nth-child(2) { animation-delay: .09s; }
.stagger > *:nth-child(3) { animation-delay: .14s; }
.stagger > *:nth-child(4) { animation-delay: .19s; }
.stagger > *:nth-child(5) { animation-delay: .24s; }
.stagger > *:nth-child(6) { animation-delay: .29s; }
.stagger > *:nth-child(7) { animation-delay: .34s; }
.stagger > *:nth-child(8) { animation-delay: .39s; }
.stagger > *:nth-child(n+9) { animation-delay: .44s; }

/* Sections below the fold wait until they are actually scrolled to.
   Gated on .js so that if the script never runs, the content is simply
   visible rather than stuck at opacity 0 forever. */
.js .reveal { opacity: 0; transform: translateY(22px); transition: opacity .6s var(--ease), transform .6s var(--ease); }
.js .reveal.shown { opacity: 1; transform: none; }

/* Loading placeholder that reads as "working", not "broken". */
.skeleton {
  background: linear-gradient(90deg, var(--panel2) 25%, #221f2a 50%, var(--panel2) 75%);
  background-size: 200% 100%;
  animation: shimmer 1.4s linear infinite;
  border-radius: 8px;
  color: transparent !important;
  user-select: none;
}

.js .rc-item { opacity: 0; transform: translateY(20px); transition: opacity .55s var(--ease), transform .55s var(--ease); }
.js .rc-item.shown { opacity: 1; transform: none; }

#scrollbar {
  position: fixed; top: 0; left: 0; right: 0; height: 2px; z-index: 60;
  background: linear-gradient(90deg, var(--accent), #fff);
  transform: scaleX(0); transform-origin: 0 50%;
  pointer-events: none;
}

/* ---------- nav ---------- */

/* Flat and edge-to-edge at rest; condenses into a floating rounded shell
   once the page is scrolled, so the corners appear rather than being there
   the whole time. */
nav.top {
  animation: fadeDown .5s var(--ease) both;
  position: sticky;
  top: 0;
  z-index: 50;
  background: transparent;
  border-bottom: 1px solid transparent;
  /* backdrop-filter is deliberately NOT transitioned. Animating it makes the
     browser re-blur everything behind the bar on every frame of the
     transition, and it happens at exactly the moment the page is already
     busy scrolling. The blur snaps on instead; nobody notices, and the
     scroll stops stuttering at the top of every page. */
  transition: background .35s var(--ease), border-color .35s var(--ease),
              padding .35s var(--ease);
}
nav.top .inner {
  transition: background .35s var(--ease), border-color .35s var(--ease),
              border-radius .35s var(--ease), box-shadow .35s var(--ease),
              max-width .35s var(--ease);
  border: 1px solid transparent;
  border-radius: 0;
}
nav.top.scrolled { padding: .5rem 1rem 0; }
nav.top.scrolled .inner {
  max-width: 1040px;
  background: rgba(15, 13, 18, .62);
  backdrop-filter: blur(14px);
  border-color: var(--line);
  border-radius: 999px;
  box-shadow: 0 8px 30px rgba(0, 0, 0, .45);
}
nav.top .inner {
  max-width: 1100px;
  margin: 0 auto;
  padding: .55rem 1.1rem;
  display: flex;
  align-items: center;
  gap: .75rem;
  min-height: 58px;
}
nav.top .brand { display: flex; align-items: center; flex: 0 0 auto; }
nav.top .brand img { display: block; width: 32px; height: 32px; border-radius: 10px; background: none; }
nav.top .links { position: relative; display: flex; align-items: center; gap: .1rem; margin-left: .5rem; }
nav.top .links a {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: .42rem;
  color: var(--muted);
  font-size: .88rem;
  font-weight: 500;
  line-height: 1;
  padding: .5rem .8rem;
  border-radius: 10px;
  white-space: nowrap;
  transition: color .18s var(--ease);
}
nav.top .links a:hover, nav.top .links a.active { color: #fff; }

/* One pill that slides between links, rather than six that fade in and out. */
.navind {
  position: absolute;
  top: 50%;
  left: 0;
  height: 32px;
  margin-top: -16px;
  border-radius: 10px;
  background: rgba(179,164,200,.13);
  border: 1px solid rgba(179,164,200,.10);
  opacity: 0;
  pointer-events: none;
  transition: transform .3s var(--ease), width .3s var(--ease), opacity .2s var(--ease);
}
nav.top .links a svg { width: 15px; height: 15px; flex: 0 0 auto; opacity: .8; }
nav.top .links a:hover svg, nav.top .links a.active svg { opacity: 1; }
nav.top .spacer { flex: 1; }

.langwrap { position: relative; display: flex; align-items: center; flex: 0 0 auto; }
.langbtn {
  display: inline-flex; align-items: center; gap: .35rem;
  background: transparent; border: 1px solid transparent; color: var(--muted);
  border-radius: 999px; padding: .35rem .6rem; cursor: pointer; font: inherit; font-size: .82rem;
  transition: color .2s var(--ease), border-color .2s var(--ease), background .2s var(--ease);
}
.langbtn:hover { color: #fff; background: rgba(179,164,200,.08); }
.langbtn { border-color: var(--line); background: var(--panel); border-radius: 10px; padding: .44rem .6rem; line-height: 1; }
.langbtn .flag { font-weight: 600; letter-spacing: .04em; font-size: .78rem; }
.flagimg { width: 18px; height: 12px; border-radius: 2px; flex: 0 0 auto; }
.langbtn svg { width: 13px; height: 13px; }
/* Opens from the corner it is anchored to rather than sliding up from below.
   fadeUp moved the whole panel 16px, which on a menu hanging off a button
   reads as the menu arriving from somewhere else; scaling out of the top
   right, where the button is, reads as the button opening. */
@keyframes menuIn {
  from { opacity: 0; transform: translateY(-4px) scale(.96); }
  to   { opacity: 1; transform: none; }
}
.langmenu {
  position: absolute; right: 0; top: calc(100% + .5rem); min-width: 190px;
  background: var(--panel-solid); border: 1px solid var(--line-hi); border-radius: 14px;
  padding: .4rem; box-shadow: var(--shadow); z-index: 60;
  transform-origin: top right;
  animation: menuIn .18s var(--ease) both;
}
/* Each row arrives just behind the panel, so the menu unfolds rather than
   appearing all at once. Capped at six because past that the last row is
   waiting long enough to feel slow. */
@keyframes menuRowIn {
  from { opacity: 0; transform: translateY(-3px); }
  to   { opacity: 1; transform: none; }
}
.langmenu .langopt { animation: menuRowIn .2s var(--ease) both; }
.langmenu .langopt:nth-child(1) { animation-delay: .03s; }
.langmenu .langopt:nth-child(2) { animation-delay: .05s; }
.langmenu .langopt:nth-child(3) { animation-delay: .07s; }
.langmenu .langopt:nth-child(4) { animation-delay: .09s; }
.langmenu .langopt:nth-child(5) { animation-delay: .11s; }
.langmenu .langopt:nth-child(n+6) { animation-delay: .13s; }

@media (prefers-reduced-motion: reduce) {
  .langmenu, .langmenu .langopt { animation: none; }
}
.langopt {
  display: block; width: 100%; text-align: left; background: none; border: 0;
  color: var(--muted); font: inherit; font-size: .88rem; padding: .45rem .6rem;
  border-radius: 9px; cursor: pointer;
}
.langopt { display: flex; align-items: center; gap: .6rem; }
.langopt { transition: background .15s var(--ease), color .15s var(--ease); }
.langopt:hover { background: rgba(179,164,200,.1); color: #fff; }
.lflag {
  font-size: .66rem; font-weight: 700; letter-spacing: .04em;
  background: rgba(179,164,200,.14); border: 1px solid var(--line);
  border-radius: 4px; padding: .1rem .3rem; min-width: 26px; text-align: center;
}
.langopt.active { color: #fff; background: rgba(179,164,200,.14); }
.langnote { margin: .35rem .6rem .2rem; }

/* ---------- buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  padding: .6rem 1.15rem;
  border-radius: 999px;
  font-weight: 600;
  font-size: .92rem;
  border: 1px solid var(--line-hi);
  background: var(--panel2);
  color: #fff;
  cursor: pointer;
  font-family: inherit;
  transition: background .22s var(--ease), border-color .22s var(--ease), transform .22s var(--ease), opacity .22s var(--ease);
}
.btn:hover { transform: translateY(-1px); border-color: var(--accent); }
.btn svg { width: 18px; height: 18px; flex: 0 0 auto; }

.btn.discord { background: var(--discord); border-color: var(--discord); }
.btn.discord:hover { background: #4752c4; border-color: #4752c4; }

.btn.primary { background: linear-gradient(180deg, rgba(179,164,200,.25), rgba(179,164,200,.1)); }
.btn.primary:hover { background: linear-gradient(180deg, rgba(179,164,200,.36), rgba(179,164,200,.18)); }

.btn.ghost { background: transparent; color: var(--muted); }
.btn.ghost:hover { background: var(--panel2); color: #fff; }

.btn.small { padding: .48rem .85rem; font-size: .84rem; line-height: 1; }

/* Signed-in chip replacing the login button. */
.me {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  padding: .28rem .7rem .28rem .28rem;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: var(--panel);
  font-size: .84rem;
  font-weight: 500;
  line-height: 1;
  flex: 0 0 auto;
}
.me img { display: block; width: 26px; height: 26px; border-radius: 7px; }
.me > span { line-height: 1; }
.me .out { color: var(--dim); cursor: pointer; font-size: .78rem; background: none; border: 0; font-family: inherit; padding: 0 0 0 .3rem; }
.me .out:hover { color: var(--red); }

/* ---------- layout ---------- */

main { position: relative; z-index: 1; max-width: 1100px; margin: 0 auto; padding: 4rem 1.5rem 5rem; }

h1 { font-size: clamp(2.1rem, 5.5vw, 3.2rem); margin: 0 0 .7rem; letter-spacing: -.04em; line-height: 1.12; font-weight: 700; }
h2 { font-size: 1.55rem; margin: 0 0 1.1rem; letter-spacing: -.03em; font-weight: 650; }
h3 { font-size: 1.05rem; margin: 0 0 .35rem; letter-spacing: -.02em; font-weight: 600; }

.grad {
  background: linear-gradient(to right, var(--accent) 0%, #fff 55%, var(--accent) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.squiggle { position: relative; display: inline-block; padding: 0 2px; }

/* A brush stroke that tapers at both ends, drawn once as the hero settles.
   Reads as marked-by-hand rather than as a generic underline. */
.squiggle::after {
  content: "";
  position: absolute;
  left: -2%;
  bottom: -.18em;
  width: 104%;
  height: .34em;
  background: linear-gradient(95deg, var(--sakura), var(--cream) 45%, var(--teal));
  border-radius: 50%;
  transform-origin: left center;
  -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 24' preserveAspectRatio='none'><path d='M4 16 C 40 6, 78 20, 116 11 S 176 6, 196 14 L 196 19 C 172 12, 140 24, 110 17 S 44 13, 4 21 Z' fill='%23000'/></svg>");
  mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 24' preserveAspectRatio='none'><path d='M4 16 C 40 6, 78 20, 116 11 S 176 6, 196 14 L 196 19 C 172 12, 140 24, 110 17 S 44 13, 4 21 Z' fill='%23000'/></svg>");
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
  animation: strokeIn 1s var(--ease) .35s both;
  pointer-events: none;
}

@keyframes strokeIn {
  from { transform: scaleX(0); opacity: 0; }
  to   { transform: scaleX(1); opacity: 1; }
}

.lede { color: var(--muted); font-size: 1.08rem; max-width: 56ch; margin: 0 0 2rem; }
.center { text-align: center; }
.center .lede { margin-left: auto; margin-right: auto; }
.muted { color: var(--muted); }
.small { font-size: .85rem; }
.dim { color: var(--dim); }

.hero { padding: 3.5rem 0 4rem; }
.hero .mark { width: 96px; height: 96px; margin: 0 auto 1.6rem; border-radius: 22px; overflow: hidden; }
.hero .mark.bare { background: none; border: 0; box-shadow: none; }
.hero .mark img { width: 100%; height: 100%; object-fit: cover; }
.cta { display: flex; gap: .7rem; justify-content: center; flex-wrap: wrap; margin-top: 1.8rem; }

.btn.lg { padding: .85rem 1.5rem; font-size: 1rem; }
.btn .arr { margin-left: .15rem; transition: transform .2s var(--ease); display: inline-block; }
.btn:hover .arr { transform: translateX(3px); }

.steps-grid { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
.stepcard {
  background: var(--panel); border: 1px solid var(--line); border-radius: 12px;
  padding: 1.6rem 1.5rem; position: relative; overflow: hidden;
  transition: border-color .35s var(--ease), transform .35s var(--ease);
}
.stepcard:hover { border-color: var(--line-hi); transform: translateY(-3px); }
.stepno {
  position: absolute; top: .9rem; right: 1.2rem;
  font-size: 2.4rem; font-weight: 700; letter-spacing: -.05em;
  color: rgba(179,164,200,.09);
}
.stepcard h3 { margin-bottom: .45rem; }
.stepcard p { margin: 0; color: var(--muted); font-size: .92rem; }

.split { display: grid; gap: 2rem; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); align-items: center; }
.quotecard {
  background: var(--panel); border: 1px solid var(--line); border-radius: 12px; padding: 1.6rem;
}
.quotecard code {
  display: inline-block; background: rgba(179,164,200,.1); border: 1px solid var(--line);
  padding: .45rem .8rem; border-radius: 10px; color: #ded6ec; font-size: .92rem;
}

.cta-band {
  text-align: center; padding: 3.5rem 1.5rem;
  border: 1px solid var(--line); border-radius: var(--r-card);
  background: radial-gradient(ellipse at 50% 0%, rgba(179,164,200,.12), transparent 60%), var(--panel);
}
.cta-band h2 { margin-bottom: .4rem; }
.cta-band p { margin: 0; }

/* anti-nuke module grid */
.fgrid { display: grid; gap: .9rem; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); }
.modgrid { display: grid; gap: .4rem; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); margin-top: .3rem; }
.modrow {
  display: flex; align-items: center; gap: .55rem; cursor: pointer;
  padding: .45rem .6rem; border: 1px solid var(--line); border-radius: 10px;
  background: #0b0910; font-size: .87rem; color: var(--muted);
  transition: border-color .2s var(--ease), color .2s var(--ease);
}
.modrow:hover { border-color: var(--line-hi); color: #fff; }
.modrow input { accent-color: var(--accent); width: auto; }

/* Server showcase treadmill */
.marquee-wrap { margin: 2.4rem 0 2rem; }
.marquee {
  overflow: hidden; position: relative;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.marquee-track { display: flex; gap: .8rem; width: max-content; animation: treadmill 46s linear infinite; will-change: transform; }
.marquee[data-idle] .marquee-track { animation-play-state: paused; }
.marquee:hover .marquee-track { animation-play-state: paused; }
@keyframes treadmill { from { transform: translateX(0); } to { transform: translateX(-50%); } }
.mcard {
  display: flex; align-items: center; gap: .7rem; flex: 0 0 auto;
  background: none; border: 0; border-radius: 0;
  padding: .55rem 1.4rem .55rem 0; min-width: 0;
}
.mcard img, .mcard .micon { width: 34px; height: 34px; border-radius: 8px; flex: 0 0 auto; object-fit: cover; background: var(--panel2); }
.mcard .micon { display: grid; place-items: center; color: var(--dim); font-weight: 600; border: 1px solid var(--line); }
.mcard .mtext { display: flex; flex-direction: column; line-height: 1.3; min-width: 0; }
.mcard .mtext strong { font-size: .88rem; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 190px; }
.mcard .mtext span { font-size: .78rem; color: var(--dim); }

/* Platform strip */
.platgrid { display: grid; gap: .8rem; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); margin-top: 1.6rem; }
.plat {
  position: relative; overflow: hidden;
  background: var(--panel); border: 1px solid var(--line); border-radius: 10px;
  padding: 1.1rem 1.2rem;
  transition: border-color .3s var(--ease), transform .3s var(--ease);
}
.plat::before {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(ellipse at 0% 0%, currentColor, transparent 62%);
  opacity: .10; pointer-events: none;
}
.plat:hover { transform: translateY(-2px); border-color: var(--line-hi); }
.plat { display: flex; align-items: center; gap: .9rem; }
.plogo {
  width: 38px; height: 38px; flex: 0 0 auto; border-radius: 9px;
  display: grid; place-items: center;
  background: color-mix(in srgb, currentColor 16%, transparent);
  border: 1px solid color-mix(in srgb, currentColor 26%, transparent);
}
.plogo svg { width: 20px; height: 20px; }
.ptext { min-width: 0; }
.plat .pname { display: block; font-weight: 600; font-size: .96rem; letter-spacing: -.02em; margin-bottom: .1rem; color: #fff; }
.plat .pdesc { display: block; color: var(--muted); font-size: .82rem; }

.platmarquee { margin-top: 1.6rem; }
.platmarquee .marquee-track { animation-duration: 60s; gap: .8rem; }
.platmarquee .plat { flex: 0 0 auto; width: 250px; }

.tstable { width: 100%; border-collapse: collapse; font-size: .9rem; }
.tstable th { text-align: left; padding: .7rem .8rem; color: var(--dim); font-size: .7rem; text-transform: uppercase; letter-spacing: .08em; font-weight: 500; }
.tstable thead tr { border-bottom: 1px solid var(--line); }
.tstable td { padding: .7rem .8rem; border-bottom: 1px solid var(--line); vertical-align: middle; }
.tstable tbody tr:last-child td { border-bottom: 0; }
.tstable tbody tr:hover { background: rgba(179,164,200,.04); }
.tsprev { display: block; color: #fff; }
.tslabel { display: block; margin-top: .1rem; }
.tstable code { background: rgba(179,164,200,.1); border: 1px solid var(--line); padding: .2rem .5rem; border-radius: 6px; color: #ded6ec; font-size: .84rem; white-space: nowrap; }
.tstable td:last-child { text-align: right; white-space: nowrap; }
input[type="date"], input[type="time"] {
  width: 100%; padding: .6rem .8rem; background: #0b0910;
  border: 1px solid var(--line); border-radius: 8px; color: var(--text);
  font: inherit; font-size: .92rem; color-scheme: dark;
}
input[type="date"]:focus, input[type="time"]:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(179,164,200,.12); }

.tsteaser {
  margin-top: 1.4rem;
  background: linear-gradient(180deg, rgba(255,255,255,.042), rgba(255,255,255,.01));
  border: 1px solid rgba(255,255,255,.07);
  border-radius: 12px; padding: 1.2rem 1.3rem;
  display: flex; flex-direction: column; gap: .7rem; align-items: flex-start;
}
.tsrow { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; width: 100%; }
.tsrow .tsprev { color: #fff; font-size: .93rem; flex: 1; min-width: 190px; }
.tsrow code {
  background: rgba(179,164,200,.1); border: 1px solid var(--line);
  padding: .22rem .55rem; border-radius: 6px; color: #ded6ec; font-size: .84rem; white-space: nowrap;
}

/* FAQ accordion */
.faq-body { display: grid; gap: .35rem; }
.faq-item { border: 1px solid var(--line); border-radius: 10px; background: #0b0910; overflow: hidden; transition: border-color .25s var(--ease); }
.faq-item:hover { border-color: var(--line-hi); }
.faq-item.open { border-color: var(--accent); }
.faq-q {
  width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  background: none; border: 0; color: #fff; font: inherit; font-size: .95rem; font-weight: 500;
  padding: .95rem 1.1rem; cursor: pointer; text-align: left;
}
.faq-q svg { width: 16px; height: 16px; flex: 0 0 auto; color: var(--dim); transition: transform .28s var(--ease); }
.faq-item.open .faq-q svg { transform: rotate(180deg); color: var(--accent); }
.faq-a { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .3s var(--ease); }
.faq-item.open .faq-a { grid-template-rows: 1fr; }
.faq-a > p { overflow: hidden; margin: 0; padding: 0 1.1rem; color: var(--muted); font-size: .92rem; }
.faq-item.open .faq-a > p { padding-bottom: 1.05rem; }

/* ---------- tiles / panels ---------- */

.grid { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }
.tile {
  background: linear-gradient(180deg, rgba(255,255,255,.045), rgba(255,255,255,.012));
  border: 1px solid rgba(255,255,255,.07);
  border-radius: 12px;
  padding: 1.3rem 1.45rem;
  transition: border-color .35s var(--ease), transform .35s var(--ease), background .35s var(--ease);
}
.tile:hover {
  border-color: rgba(247,183,203,.28);
  background: linear-gradient(180deg, rgba(255,255,255,.07), rgba(255,255,255,.02));
  transform: translateY(-3px);
}
.tile .k { color: var(--dim); font-size: .72rem; text-transform: uppercase; letter-spacing: .09em; font-weight: 500; }
.tile .v { font-size: 1.95rem; font-weight: 650; margin-top: .3rem; letter-spacing: -.035em; }

.panel {
  background: linear-gradient(180deg, rgba(255,255,255,.042), rgba(255,255,255,.01));
  border: 1px solid rgba(255,255,255,.07);
  border-radius: var(--r-card);
  padding: 1.6rem;
  transition: border-color .35s var(--ease), transform .35s var(--ease), background .35s var(--ease);
}
.panel:hover {
  border-color: rgba(247,183,203,.26);
  background: linear-gradient(180deg, rgba(255,255,255,.065), rgba(255,255,255,.018));
  transform: translateY(-2px);
}

.features { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.features .panel p { margin: 0; color: var(--muted); font-size: .92rem; }
.features .panel:hover h3 { color: var(--accent); }
.features .panel h3 { transition: color .3s; }

/* ---------- status pips ---------- */

.pip { width: 9px; height: 9px; border-radius: 50%; background: var(--dim); display: inline-block; flex: 0 0 auto; }
.pip.on { background: var(--green); box-shadow: 0 0 0 3px rgba(110,231,168,.15); animation: pulse 2.4s var(--ease) infinite; }
.pip.warn { background: var(--amber); box-shadow: 0 0 0 3px rgba(251,191,36,.15); }
.pip.off { background: var(--red); box-shadow: 0 0 0 3px rgba(248,113,113,.15); }

.statusline { display: inline-flex; align-items: center; gap: .55rem; color: var(--dim); font-size: .88rem; }

.statebar {
  display: flex;
  align-items: center;
  gap: .8rem;
  padding: 1.1rem 1.4rem;
  border-radius: 12px;
  border: 1px solid var(--line);
  background: var(--panel);
  margin-bottom: 1.4rem;
}
.statebar strong { font-size: 1.05rem; }

/* ---------- commands ---------- */

.toolbar { display: flex; gap: .7rem; flex-wrap: wrap; align-items: center; margin-bottom: 1.4rem; }
input[type="search"], input[type="text"] {
  flex: 1;
  min-width: 220px;
  padding: .7rem 1rem;
  background: #0b0910;
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--text);
  font: inherit;
  font-size: .93rem;
}
input::placeholder { color: #52525b; }
input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(179,164,200,.12); }

.chips { display: flex; gap: .4rem; flex-wrap: wrap; }
.chip {
  padding: .4rem .85rem;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--panel);
  color: var(--muted);
  font-size: .84rem;
  font-weight: 500;
  cursor: pointer;
  font-family: inherit;
  transition: border-color .22s var(--ease), color .22s var(--ease), background .22s var(--ease), transform .22s var(--ease);
}
.chip:hover { color: #fff; border-color: var(--line-hi); transform: translateY(-1px); }
.chip.active { color: #fff; background: rgba(179,164,200,.15); border-color: var(--accent); }

.cmdlist { display: grid; gap: .7rem; }
.cmd {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 1rem 1.2rem;
  transition: border-color .25s var(--ease), transform .25s var(--ease);
}
.cmd:hover { border-color: var(--line-hi); transform: translateX(3px); }
.cmd .head { display: flex; align-items: baseline; gap: .7rem; flex-wrap: wrap; }
.cmd code.name { background: rgba(179,164,200,.12); border: 1px solid var(--line); color: #e6dff2; padding: .18rem .6rem; border-radius: 8px; font-size: .92rem; font-weight: 600; }
.cmd .cat { font-size: .72rem; text-transform: uppercase; letter-spacing: .08em; color: var(--dim); }
.cmd .desc { color: var(--muted); font-size: .92rem; margin: .45rem 0 0; }
.cmd .subs { display: flex; flex-wrap: wrap; gap: .35rem; margin-top: .7rem; }
.cmd .subs span { font-size: .78rem; padding: .18rem .55rem; border-radius: 999px; background: rgba(179,164,200,.07); border: 1px solid var(--line); color: var(--muted); }

table { width: 100%; border-collapse: collapse; font-size: .9rem; }
th, td { text-align: left; padding: .7rem .8rem; white-space: nowrap; }
th { color: var(--dim); font-weight: 500; font-size: .72rem; text-transform: uppercase; letter-spacing: .08em; }
thead tr { border-bottom: 1px solid var(--line); }
tbody tr:hover { background: rgba(179,164,200,.05); }
tbody td:first-child { border-radius: 10px 0 0 10px; }
tbody td:last-child { border-radius: 0 10px 10px 0; }

footer {
  position: relative;
  margin-top: 6rem;
  overflow: hidden;
  border-top: 1px solid rgba(255,255,255,.06);
}

/* A wash that rises out of the page instead of a hard band across it. */
footer::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(70% 130% at 50% 120%, rgba(247,183,203,.16), transparent 62%),
    radial-gradient(50% 100% at 12% 110%, rgba(127,209,196,.10), transparent 62%),
    radial-gradient(55% 110% at 88% 110%, rgba(179,164,200,.13), transparent 62%);
}

/* The closing pitch, centred, with the mark above it. */
footer .fhero {
  position: relative;
  z-index: 1;
  max-width: 720px;
  margin: 0 auto;
  padding: 4.5rem 1.5rem 3rem;
  text-align: center;
}
footer .fmark {
  width: 68px; height: 68px; border-radius: 20px; display: block;
  margin: 0 auto 1.2rem;
}
footer .fbig {
  font-size: clamp(1.7rem, 4vw, 2.6rem);
  letter-spacing: -.04em;
  margin: 0 0 1.6rem;
  background: linear-gradient(100deg, #fff 35%, var(--sakura) 75%, var(--plum));
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
footer .fcta { display: flex; gap: .7rem; justify-content: center; flex-wrap: wrap; }

footer .finner {
  position: relative;
  z-index: 1;
  max-width: 1100px;
  margin: 0 auto;
  padding: 1rem 1.5rem 2rem;
  display: flex;
  justify-content: center;
}

footer .fcols { display: flex; gap: 4.5rem; flex-wrap: wrap; justify-content: center; text-align: left; }
footer .fcols h4 {
  margin: 0 0 .8rem;
  font-size: .74rem;
  text-transform: uppercase;
  letter-spacing: .1em;
  color: var(--dim);
  font-weight: 600;
}
footer .fcols a {
  display: flex; align-items: center; gap: .5rem;
  color: var(--muted); font-size: .88rem; padding: .3rem 0;
  transition: color .18s var(--ease);
}
footer .fcols a svg { width: 14px; height: 14px; flex: 0 0 auto; opacity: .65; transition: opacity .18s var(--ease), color .18s var(--ease); }
footer .fcols a:hover { color: #fff; }
footer .fcols a:hover svg { opacity: 1; color: var(--sakura); }
footer .fstate svg { width: 13px; height: 13px; opacity: .7; }

footer .fbottom {
  position: relative;
  z-index: 1;
  max-width: 1100px;
  margin: 0 auto;
  padding: 1.2rem 1.5rem 2.5rem;
  border-top: 1px solid rgba(255,255,255,.06);
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
}
footer .fstate {
  display: inline-flex; align-items: center; gap: .45rem;
  color: var(--dim); padding: .3rem .7rem; border-radius: 999px;
  border: 1px solid rgba(255,255,255,.07); background: rgba(255,255,255,.03);
  transition: color .2s var(--ease), border-color .2s var(--ease);
}
footer .fstate:hover { color: #fff; border-color: rgba(255,255,255,.16); }

@media (max-width: 620px) {
  footer .fcols { gap: 2rem; }
  footer .fhero { padding: 3rem 1.2rem 2rem; }
  footer .fcta { flex-direction: column; }
  footer .fcta .btn { width: 100%; justify-content: center; }
}
footer .spacer { flex: 1; }

/* ---------- status page ---------- */

main.narrow { max-width: 720px; }
main.wide { max-width: 980px; }

.stitle { display: flex; align-items: center; justify-content: space-between; gap: 1rem; margin-bottom: 1.6rem; flex-wrap: wrap; }
.stitle .row { display: flex; align-items: center; gap: .6rem; }
.stitle strong { font-size: 1.15rem; letter-spacing: -.02em; }
.stitle .tag {
  border-radius: 999px;
  background: var(--panel2);
  border: 1px solid var(--line);
  padding: .15rem .6rem;
  font-size: .72rem;
  color: var(--dim);
  font-weight: 500;
}

/* The headline verdict, tinted by severity. */
.bigstate {
  margin-bottom: .4rem;
  display: flex;
  align-items: center;
  gap: .9rem;
  padding: 1.3rem 1.4rem;
  border-radius: 12px;
  border: 1px solid var(--line);
  background: var(--panel);
  margin-bottom: 1.4rem;
  transition: border-color .3s, background .3s;
}
.bigstate strong { font-size: 1.1rem; display: block; letter-spacing: -.02em; }
.bigstate.on { border-color: rgba(110,231,168,.3); background: rgba(110,231,168,.05); }
.bigstate.warn { border-color: rgba(251,191,36,.3); background: rgba(251,191,36,.05); }
.bigstate.off { border-color: rgba(248,113,113,.3); background: rgba(248,113,113,.05); }

.services { border: 1px solid var(--line); border-radius: 10px; overflow: hidden; background: var(--panel); }
.svc {
  display: flex;
  align-items: center;
  gap: .8rem;
  padding: .95rem 1.3rem;
  border-bottom: 1px solid var(--line);
}
.svc:last-child { border-bottom: 0; }
.svc { transition: background .25s var(--ease); }
.svc:hover { background: rgba(179,164,200,.04); }
.svc .sname { flex: 1; font-size: .94rem; font-weight: 500; }
.svc .sval { color: var(--muted); font-size: .86rem; }

.metrics {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: 10px;
  overflow: hidden;
  /* No top margin. It sits inside a titled band now, and the band already
     spaces itself - keeping both put a gap under the heading twice. */
}
.metrics > div { background: var(--panel); padding: 1.15rem 1.3rem; display: flex; flex-direction: column; gap: .25rem; }
.metrics .mk { color: var(--dim); font-size: .72rem; text-transform: uppercase; letter-spacing: .09em; font-weight: 500; }
.metrics .mv { font-size: 1.3rem; font-weight: 600; letter-spacing: -.02em; }

/* Grouped service sections with a rollup badge per group. */
.sgroup {
  border: 1px solid rgba(255,255,255,.07);
  border-radius: 12px;
  background: linear-gradient(180deg, rgba(255,255,255,.04), rgba(255,255,255,.01));
  overflow: hidden;
  margin-bottom: 1rem;
}
.sghead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1rem 1.3rem;
  background: rgba(255, 255, 255, .015);
  border-bottom: 1px solid var(--line);
}
.sghead h2 { margin: 0; font-size: 1rem; letter-spacing: -.02em; font-weight: 600; }
.sgstate { display: inline-flex; align-items: center; gap: .45rem; font-size: .84rem; font-weight: 500; }
.sgstate.on { color: var(--green); }
.sgstate.warn { color: var(--amber); }
.sgstate.off { color: var(--red); }
.sgbody .svc:last-child { border-bottom: 0; }

/* Server cards on the setup page. */
.gcard { gap: .9rem; }
.gicon { width: 32px; height: 32px; border-radius: 10px; flex: 0 0 auto; object-fit: cover; background: var(--panel2); }
.gicon.blank {
  display: grid; place-items: center;
  border: 1px solid var(--line); color: var(--dim);
  font-size: .85rem; font-weight: 600;
}
.gcard .sname { font-weight: 500; }
.gcard .cat { margin-left: .5rem; }

/* Settings forms on the setup page. */
.flabel { display: block; font-size: .74rem; text-transform: uppercase; letter-spacing: .08em; color: var(--dim); margin: .9rem 0 .35rem; font-weight: 500; }
/* Text inputs were missing here, which left every one of them rendering as an
   unstyled browser control next to properly styled selects. */
.sgbody select,
.sgbody textarea,
.sgbody input:not([type="checkbox"]):not([type="radio"]):not([type="color"]) {
  width: 100%; padding: .6rem .8rem; background: #0b0910;
  border: 1px solid var(--line); border-radius: 10px; color: var(--text);
  font: inherit; font-size: .88rem; transition: border-color .2s var(--ease), box-shadow .2s var(--ease);
}
.sgbody select:focus,
.sgbody textarea:focus,
.sgbody input:not([type="checkbox"]):not([type="radio"]):not([type="color"]):focus {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(179,164,200,.12);
}
/* The drawn listbox replaced the native selects in these panes, so it has to
   sit in exactly the box they did. Its own min-width is sized for the newer
   pages, where it is a control on the right of a row rather than a form field
   filling a column, and would otherwise blow the narrow grid cells open. */
.sgbody .ct-pick, .whform .ct-pick { width: 100%; min-width: 0; }
.sgbody .ct-pick-btn {
  padding: .6rem .8rem; background: #0b0910; font-size: .88rem; border-radius: 10px;
}
.sgbody .ct-pick-btn:focus-visible {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(179,164,200,.12);
}
.lvadd .ct-pick { flex: 1; min-width: 140px; width: auto; }

.sgbody input::placeholder, .sgbody textarea::placeholder { color: var(--dim); }
.sgbody textarea { resize: vertical; min-height: 62px; }
.sgbody code { background: rgba(179,164,200,.1); border: 1px solid var(--line); padding: .05rem .35rem; border-radius: 5px; font-size: .82em; }

/* Toggle */
.switch { position: relative; display: inline-block; width: 42px; height: 24px; flex: 0 0 auto; }
.switch input { opacity: 0; width: 0; height: 0; }
.switch span {
  position: absolute; inset: 0; cursor: pointer;
  background: var(--panel2); border: 1px solid var(--line); border-radius: 999px;
  transition: background .25s var(--ease), border-color .25s var(--ease);
}
.switch span::before {
  content: ""; position: absolute; height: 16px; width: 16px; left: 3px; top: 3px;
  background: var(--dim); border-radius: 50%; transition: transform .25s var(--ease), background .25s var(--ease);
}
.switch input:checked + span { background: rgba(110,231,168,.2); border-color: var(--green); }
.switch input:checked + span::before { transform: translateX(18px); background: var(--green); }

.saverow { display: flex; align-items: center; gap: 1rem; margin-top: 1.4rem; flex-wrap: wrap; }
.ok-text { color: var(--green); }
.err-text { color: var(--red); }

.docsec-wrap h2 { margin: 2rem 0 .6rem; font-size: 1.2rem; }
.docsec-wrap h3 { margin: 1.3rem 0 .4rem; color: #fff; font-size: .98rem; }
.docsec-wrap p { margin: 0 0 .9rem; }
.docsec-wrap code { background: rgba(179,164,200,.1); border: 1px solid var(--line); padding: .08rem .38rem; border-radius: 6px; font-size: .87em; color: #ded6ec; }
.sgbody h3 { margin: 1.2rem 0 .35rem; font-size: .96rem; color: #fff; }
.sgbody h3:first-child { margin-top: 0; }
.sgbody p { margin: 0 0 .3rem; }

/* ---------- docs ---------- */

.docwrap {
  position: relative;
  z-index: 1;
  max-width: 1100px;
  margin: 0 auto;
  padding: 3rem 1.5rem 4rem;
  display: grid;
  grid-template-columns: 220px minmax(0, 1fr) 190px;
  gap: 2.6rem;
  align-items: start;
}
.docnav { position: sticky; top: 5rem; max-height: calc(100vh - 7rem); overflow-y: auto; scrollbar-width: none; }
.docnav::-webkit-scrollbar { width: 0; }
.docnav-inner { display: flex; flex-direction: column; gap: .1rem; }
.docnav a {
  color: var(--dim);
  font-size: .88rem;
  padding: .4rem .9rem;
  margin-left: -1px;
  border-left: 2px solid transparent;
  transition: color .2s var(--ease), border-color .2s var(--ease);
}
.docnav a:hover { color: var(--muted); }
.docnav a.active { color: #fff; border-left-color: var(--accent); }

.doccontent { min-width: 0; }
.docsec { scroll-margin-top: 5rem; padding-bottom: 2.5rem; margin-bottom: 2.5rem; border-bottom: 1px solid var(--line); }
.docsec:last-child { border-bottom: 0; }
.docsec h2 { margin-top: 0; }
.docsec h3 { margin: 1.6rem 0 .5rem; color: var(--muted); font-size: .95rem; }
.docsec p { margin: 0 0 1rem; }
.docsec code {
  background: rgba(179,164,200,.1);
  border: 1px solid var(--line);
  color: #ded6ec;
  padding: .1rem .4rem;
  border-radius: 6px;
  font-size: .88em;
}

.steps { margin: 0; padding-left: 1.2rem; color: var(--muted); }
.steps li { margin-bottom: .7rem; }
.steps strong { color: #fff; }

.note {
  border: 1px solid var(--line-hi);
  border-left: 3px solid var(--accent);
  background: rgba(179,164,200,.05);
  border-radius: 12px;
  padding: .9rem 1.1rem;
  color: var(--muted);
  font-size: .92rem;
  margin-top: 1.2rem;
}
.note.warn { border-left-color: var(--amber); background: rgba(251,191,36,.05); }

.doctable { width: 100%; border-collapse: collapse; font-size: .9rem; margin-bottom: 1rem; }
.doctable th, .doctable td { text-align: left; padding: .65rem .8rem; vertical-align: top; white-space: normal; }
.doctable thead tr { border-bottom: 1px solid var(--line); }
.doctable td { color: var(--muted); border-bottom: 1px solid var(--line); }

.kvlist { display: grid; gap: .1rem; }
.kvlist > div {
  display: flex;
  gap: 1rem;
  align-items: baseline;
  padding: .55rem .2rem;
  border-bottom: 1px solid var(--line);
  flex-wrap: wrap;
}
.kvlist > div:last-child { border-bottom: 0; }
.kvlist span { color: var(--muted); font-size: .9rem; flex: 1; min-width: 180px; }

@media (max-width: 860px) {
  .docwrap { grid-template-columns: 1fr; gap: 1.5rem; padding: 2rem 1rem 3rem; }
  .docwrap { grid-template-columns: 1fr; gap: 1.4rem; }
  .docnav { position: static; max-height: none; }
  .docnav-inner { flex-direction: row; overflow-x: auto; border-left: 0; border-bottom: 1px solid var(--line); }
  .docgroup { display: flex; align-items: center; gap: .1rem; margin-bottom: 0; }
  .docgrouph { display: none; }
  .docnav a { border-left: 0; border-bottom: 2px solid transparent; white-space: nowrap; }
  .docnav a.active { border-left-color: transparent; border-bottom-color: var(--accent); }
}

/* back to top */
#toTop {
  position: fixed;
  right: 1.5rem;
  bottom: 1.5rem;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: var(--panel);
  color: var(--dim);
  display: grid;
  place-items: center;
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transition: opacity .25s, color .2s, border-color .2s, transform .2s;
  z-index: 40;
}
#toTop.show { opacity: 1; pointer-events: auto; }
#toTop:hover { color: #fff; border-color: var(--line-hi); transform: translateY(-2px); }
#toTop svg { width: 20px; height: 20px; }

.spin { color: var(--dim); padding: 1.4rem 0; }
.empty { color: var(--dim); padding: 2.5rem 0; text-align: center; }

/* ---------- embed showcase ----------
   Discord's Components V2 chrome, rebuilt in CSS: an accent bar, a banner,
   sections with an accessory, separators and real button rows. Colours are
   Discord's own so the mock reads as the product, not as our site. */

.showcase { display: grid; grid-template-columns: 290px 1fr; gap: 1.6rem; margin-top: 1.8rem; align-items: start; }

.epicks { display: flex; flex-direction: column; gap: .3rem; }
.epick {
  display: flex; flex-direction: column; gap: .22rem; align-items: flex-start;
  text-align: left; width: 100%; cursor: pointer; font: inherit;
  padding: .7rem .85rem; border-radius: 10px;
  background: transparent; border: 1px solid transparent; color: var(--muted);
  transition: background .18s var(--ease), border-color .18s var(--ease), color .18s var(--ease);
}
.epick:hover { background: rgba(255,255,255,.04); color: #fff; }
.epick.active { background: rgba(88,101,242,.13); border-color: rgba(88,101,242,.34); color: #fff; }
.epick code { font-size: .88rem; font-weight: 600; color: #cdbfe4; background: none; border: 0; padding: 0; }
.epick.active code { color: #fff; }
.epick span { font-size: .78rem; color: var(--dim); line-height: 1.45; }

.estage {
  background: #313338;
  border: 1px solid #1e1f22;
  border-radius: 10px;
  padding: 1rem .9rem;
  transition: opacity .13s var(--ease);
  overflow: hidden;
}
.estage.swapping { opacity: 0; }

.dmsg { display: flex; gap: .85rem; padding: .25rem 0 .45rem; }
.davatar { width: 40px; height: 40px; border-radius: 50%; flex: 0 0 auto; background: #1e1f22; object-fit: cover; }
.dcontent { min-width: 0; flex: 1; }
.dhead { display: flex; align-items: center; gap: .45rem; margin-bottom: .2rem; flex-wrap: wrap; }
.duser { color: #f2f3f5; font-weight: 500; font-size: .95rem; }
.dstamp { color: #949ba4; font-size: .69rem; }

.dtag {
  display: inline-flex; align-items: center; gap: .18rem;
  background: #5865F2; color: #fff; font-size: .625rem; font-weight: 600;
  letter-spacing: .02em; padding: .1rem .3rem; border-radius: 3px; line-height: 1.3;
}
.vcheck { width: 11px; height: 11px; display: block; }

/* Discord's own "X used /command" interaction header. */
.dmsg.interaction {
  align-items: center; gap: .35rem; padding: .1rem 0 .1rem 22px;
  font-size: .78rem; color: #949ba4; position: relative;
}
.dmsg.interaction::before {
  content: ""; position: absolute; left: 19px; top: 50%; bottom: -6px;
  width: 20px; border-left: 2px solid #4e5058; border-bottom: 2px solid #4e5058;
  border-bottom-left-radius: 7px; pointer-events: none;
}
.iavatar { width: 16px; height: 16px; border-radius: 50%; object-fit: cover; margin-left: 24px; }
.iwho { color: #dbdee1; font-weight: 500; }
.iused { color: #949ba4; }
.icmd { color: #c9cdfb; font-weight: 500; }

/* The container itself. */
.c-container {
  position: relative;
  background: #2b2d31;
  border-left: 4px solid var(--accent, #B3A4C8);
  border-radius: 6px;
  max-width: 540px;
  margin-top: .3rem;
  padding: .75rem .9rem .85rem;
  overflow: hidden;
}
.c-banner { height: 88px; margin: -.75rem -.9rem .7rem; }

.c-section { display: flex; gap: .9rem; align-items: flex-start; }
.c-secbody { flex: 1; min-width: 0; }
.c-acc { flex: 0 0 auto; }
.c-thumb { width: 76px; height: 76px; border-radius: 8px; object-fit: cover; background: #1e1f22; display: block; }
.c-container:has(.c-banner) .c-thumb { border-radius: 50%; border: 4px solid #2b2d31; margin-top: -34px; }

.c-heading { color: #f2f3f5; font-weight: 600; font-size: 1rem; letter-spacing: -.01em; }
.c-text { color: #dbdee1; font-size: .86rem; line-height: 1.45; margin-top: .2rem; }
.c-small { color: #b5bac1; font-size: .79rem; margin-top: .12rem; }
.c-text strong, .c-small strong, .c-heading strong { color: #fff; font-weight: 600; }
.c-text code, .c-small code { background: #1e1f22; color: #dbdee1; padding: .05rem .28rem; border-radius: 3px; font-size: .8rem; }
.c-sep { height: 1px; background: #3f4147; margin: .7rem 0; }

.c-status { margin-top: .35rem; }
.c-dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; background: #80848e; box-shadow: 0 0 0 3px #2b2d31; }

.c-pills { display: flex; flex-wrap: wrap; gap: .3rem; margin-top: .35rem; }
.c-pill { background: #1e1f22; color: #dbdee1; font-size: .76rem; padding: .2rem .5rem; border-radius: 4px; }
.c-role {
  background: rgba(88,101,242,.16); color: #c9cdfb; font-size: .76rem;
  padding: .2rem .5rem; border-radius: 4px; border: 1px solid rgba(88,101,242,.3);
}

.c-tier { display: flex; flex-direction: column; gap: 3px; margin-top: .5rem; border-radius: 4px; overflow: hidden; }
.c-trow { display: flex; gap: 3px; }
.c-tlabel { width: 32px; flex: 0 0 auto; display: grid; place-items: center; color: #1e1f22; font-weight: 700; font-size: .8rem; }
.c-tcards { display: flex; gap: 3px; flex: 1; }
.c-tcard {
  width: 32px; height: 42px; border-radius: 2px;
  background: linear-gradient(160deg, hsl(var(--h) 22% 36%), hsl(var(--h) 18% 24%));
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.05);
}

.c-row { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .5rem; max-width: 540px; }
.c-btn {
  display: inline-flex; align-items: center; gap: .35rem;
  font: inherit; font-size: .8rem; font-weight: 500; color: #fff;
  padding: .45rem .8rem; border-radius: 3px; border: 0; background: #4e5058;
  cursor: pointer; transition: filter .15s var(--ease);
}
.c-btn:hover { filter: brightness(1.15); }
.c-btn svg { width: 12px; height: 12px; }
.c-btn.primary { background: #5865F2; }
.c-btn.success { background: #248046; }
.c-btn.danger { background: #da373c; }
.c-btn.inert { cursor: default; opacity: .82; }
.c-btn.inert:hover { filter: none; }

@media (max-width: 860px) {
  .showcase { grid-template-columns: 1fr; }
  .epicks { flex-direction: row; overflow-x: auto; padding-bottom: .3rem; }
  .epick { min-width: 200px; }
}

/* ---------- greeting embed builder ---------- */

.placeholders { margin: .5rem 0 0; display: flex; flex-wrap: wrap; gap: .3rem; }
.placeholders code { font-size: .72rem; }

.embedbuilder {
  margin-top: 1.1rem;
  border: 1px solid rgba(255,255,255,.07);
  border-radius: 12px;
  background: rgba(255,255,255,.02);
  overflow: hidden;
}
.ebhead {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: .8rem 1rem;
  border-bottom: 1px solid rgba(255,255,255,.06);
}
.ebhead strong { display: block; font-size: .9rem; }
.ebhead .dim { display: block; }
.ebbody { padding: 1rem; }
.ebgrid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 1.4rem; align-items: start; }
.ebfields .flabel:first-child { margin-top: 0; }

.colourrow { display: flex; gap: .5rem; align-items: center; }
.colourrow input[type="color"] {
  width: 40px !important; height: 38px; padding: 2px; border-radius: 8px; cursor: pointer;
  border: 1px solid var(--line); background: var(--panel2); flex: 0 0 auto;
}
.colourrow input[type="text"], .colourrow input:not([type="color"]) { flex: 1; min-width: 0; }

.ebcheck {
  display: flex; align-items: center; gap: .55rem;
  margin-top: .9rem; font-size: .84rem; color: var(--muted);
  cursor: pointer; line-height: 1.35;
}
.ebcheck input[type="checkbox"] {
  width: 16px !important; height: 16px; flex: 0 0 auto; margin: 0;
  accent-color: var(--sakura); cursor: pointer;
}
.ebcheck span { flex: 1; min-width: 0; }

/* The preview mirrors Discord's own embed chrome so what you see is what
   the server gets. */
.ebpreview { position: sticky; top: 5rem; }
.pv {
  background: #313338;
  border: 1px solid #1e1f22;
  border-radius: 8px;
  padding: .8rem;
  min-height: 90px;
}
.pvcontent { color: #dbdee1; font-size: .86rem; margin-bottom: .5rem; word-break: break-word; }
.pvembed {
  position: relative;
  background: #2b2d31;
  border-left: 4px solid var(--accent, #B3A4C8);
  border-radius: 4px;
  padding: .7rem .8rem;
  min-height: 42px;
}
/* Only reserve the thumbnail gutter when there is actually a thumbnail -
   otherwise every embed without one has dead space down its right edge. */
.pvembed:has(.pvthumb) { padding-right: 5.2rem; }
.pvthumb {
  position: absolute; top: .7rem; right: .7rem;
  width: 62px; height: 62px; border-radius: 6px; object-fit: cover; background: #1e1f22;
}
.pvauthor { color: #f2f3f5; font-size: .8rem; font-weight: 600; margin-bottom: .25rem; }
.pvtitle { color: #f2f3f5; font-size: .93rem; font-weight: 600; margin-bottom: .2rem; word-break: break-word; }
.pvdesc { color: #dbdee1; font-size: .84rem; line-height: 1.45; white-space: pre-wrap; word-break: break-word; }
.pvimage { display: block; width: 100%; border-radius: 5px; margin-top: .6rem; }
.pvfooter { color: #949ba4; font-size: .72rem; margin-top: .6rem; }

@media (max-width: 860px) {
  .ebgrid { grid-template-columns: 1fr; }
  .ebpreview { position: static; }
  .pvembed { padding-right: .8rem; }
  .pvthumb { position: static; margin-bottom: .5rem; }
}

/* ---------- level rewards editor ---------- */

.lvrow {
  display: flex; align-items: center; gap: .7rem;
  padding: .5rem 0; border-bottom: 1px solid rgba(255,255,255,.05);
}
.lvlevel {
  flex: 0 0 auto; font-size: .78rem; font-weight: 600; color: #cdbfe4;
  background: rgba(179,164,200,.12); border: 1px solid rgba(179,164,200,.2);
  border-radius: 6px; padding: .18rem .5rem;
}
.lvrole { flex: 1; min-width: 0; font-size: .88rem; color: #fff; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lvadd { display: flex; gap: .5rem; align-items: center; margin-top: .7rem; flex-wrap: wrap; }
.lvadd select { flex: 1; min-width: 140px; }

/* ---------- webhook manager ---------- */

.whrow {
  display: flex; align-items: center; gap: .7rem;
  padding: .6rem 0; border-bottom: 1px solid rgba(255,255,255,.05);
}
.whav { width: 32px; height: 32px; border-radius: 50%; flex: 0 0 auto; object-fit: cover; background: rgba(179,164,200,.16); }
.whav.blank { display: block; }
.whtext { flex: 1; min-width: 0; }
.whtext strong { display: block; font-size: .9rem; color: #fff; }
.whcompose {
  padding: .8rem; margin: .5rem 0 .9rem;
  border: 1px solid rgba(255,255,255,.08); border-radius: 10px;
  background: rgba(255,255,255,.02);
}
.whcompose textarea { width: 100%; margin-bottom: .5rem; }
.whnew { margin-top: 1rem; padding-top: .9rem; border-top: 1px solid rgba(255,255,255,.06); }
.btn.danger {
  background: rgba(248,113,113,.12); border: 1px solid rgba(248,113,113,.3); color: var(--red);
}
.btn.danger:hover { background: rgba(248,113,113,.22); color: #fff; }

/* ---------- webhook composer ---------- */

.whgrid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 1.2rem; align-items: start; }
/* Deliberately not a blanket `input` - that stretched checkboxes and the
   colour swatch to the full column width. */
.whform textarea,
.whform select,
.whform input:not([type="checkbox"]):not([type="color"]) { width: 100%; }
.whform textarea { min-height: 70px; }
/* The embed half is a distinct surface so it reads as "extra", not as more
   of the same form. */
.whembed {
  margin-top: .9rem; padding: .9rem 1rem 1rem;
  border: 1px solid rgba(255,255,255,.07); border-radius: 10px;
  background: rgba(255,255,255,.02);
}
.whembed .flabel:first-child { margin-top: 0; }
.whpreview { position: sticky; top: 5rem; }
.whpreview .flabel { margin-top: 0; }

.whfield {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr) auto auto;
  gap: .45rem; align-items: center; margin-bottom: .45rem;
}
.whf-inline {
  display: flex; align-items: center; gap: .3rem;
  font-size: .72rem; color: var(--dim); white-space: nowrap; cursor: pointer;
}
.whf-inline input[type="checkbox"] {
  width: 14px !important; height: 14px; margin: 0; flex: 0 0 auto; accent-color: var(--sakura);
}
.whf-del { padding: .3rem .55rem !important; line-height: 1; flex: 0 0 auto; }
.whaddfield { margin-top: .2rem; }

/* The composer sits inside a ticket row, so it needs its own breathing room. */
.whcompose .fgrid { gap: .7rem; }
.whcompose .lvadd { margin-top: 0; }

/* Webhook preview borrows the greeting preview chrome, plus a message header. */
.pvhead { display: flex; align-items: center; gap: .45rem; margin-bottom: .35rem; }
.pvav { width: 22px; height: 22px; border-radius: 50%; object-fit: cover; background: rgba(179,164,200,.2); }
.pvav.blank { display: block; }
.pvname { color: #f2f3f5; font-size: .85rem; font-weight: 500; }
.pvbot {
  background: #5865F2; color: #fff; font-size: .58rem; font-weight: 600;
  padding: .06rem .24rem; border-radius: 3px; letter-spacing: .02em;
}
.pvfields { display: flex; flex-wrap: wrap; gap: .5rem 1rem; margin-top: .5rem; }
.pvfield { flex: 1 1 100%; min-width: 0; }
.pvfield.inline { flex: 1 1 30%; }
.pvfname { color: #f2f3f5; font-size: .78rem; font-weight: 600; margin-bottom: .1rem; }
.pvfval { color: #dbdee1; font-size: .8rem; line-height: 1.35; white-space: pre-wrap; word-break: break-word; }

@media (max-width: 860px) {
  .whgrid { grid-template-columns: 1fr; }
  .whpreview { position: static; }
  .whfield { grid-template-columns: 1fr; }
}

/* ---------- browser check ---------- */

.vwrap {
  position: fixed; inset: 0; z-index: 300;
  display: grid; place-items: center;
  background: #0a0a0a;
  opacity: 1;
  transition: opacity .26s var(--ease);
}
.vwrap:not(.shown) { opacity: 0; pointer-events: none; }
.vbox { text-align: center; display: flex; flex-direction: column; align-items: center; gap: .1rem; }
.vlogo { width: 62px; height: 62px; border-radius: 18px; margin-bottom: 1rem; }
.vspin { display: flex; gap: .34rem; margin-bottom: .9rem; }
.vspin span {
  width: 8px; height: 8px; border-radius: 50%; background: var(--sakura);
  animation: vbounce 1s var(--ease) infinite;
}
.vspin span:nth-child(2) { animation-delay: .14s; background: var(--cream); }
.vspin span:nth-child(3) { animation-delay: .28s; background: var(--teal); }
@keyframes vbounce {
  0%, 60%, 100% { transform: translateY(0); opacity: .45; }
  30% { transform: translateY(-7px); opacity: 1; }
}
.vtext { color: #fff; font-size: .98rem; font-weight: 500; margin: 0; }
.vsub { color: var(--dim); font-size: .8rem; margin: .3rem 0 0; }

/* Discord renders an invocation as a pill, not as prose. */
.dslash {
  display: inline-block;
  background: rgba(88,101,242,.18);
  color: #c9cdfb;
  padding: .1rem .42rem;
  border-radius: 4px;
  font-size: .88rem;
  font-weight: 500;
}

/* ---------- captcha ---------- */

.capwrap {
  position: fixed; inset: 0; z-index: 200;
  display: grid; place-items: center; padding: 1.2rem;
  background: rgba(0,0,0,.62);
  opacity: 0; transition: opacity .18s var(--ease);
}
.capwrap.shown { opacity: 1; }
.capbox {
  width: 100%; max-width: 330px;
  background: var(--panel-solid); border: 1px solid var(--line-hi);
  border-radius: 14px; padding: 1.1rem; box-shadow: var(--shadow);
  transform: translateY(8px) scale(.98);
  transition: transform .2s var(--ease);
}
.capwrap.shown .capbox { transform: none; }
.caphead { display: flex; align-items: center; justify-content: space-between; margin-bottom: .3rem; }
.caphead strong { font-size: .98rem; }
.capx {
  background: none; border: 0; color: var(--dim); font-size: 1.3rem;
  line-height: 1; cursor: pointer; padding: 0 .2rem; font-family: inherit;
}
.capx:hover { color: #fff; }
.capnote { color: var(--dim); font-size: .8rem; margin: 0 0 .8rem; }
.capimg {
  border-radius: 10px; overflow: hidden; background: var(--panel2);
  border: 1px solid var(--line); display: grid; place-items: center;
  min-height: 74px; margin-bottom: .7rem;
}
.capimg svg { display: block; width: 100%; height: auto; }
.capimg .spin { padding: 0; font-size: .8rem; }
.caprow { display: flex; gap: .5rem; }
.caprow input {
  flex: 1; min-width: 0; font-family: inherit; font-size: 1rem;
  letter-spacing: .22em; text-transform: uppercase; text-align: center;
  background: var(--panel2); border: 1px solid var(--line); color: #fff;
  border-radius: 9px; padding: .55rem .6rem;
}
.caprow input:focus { outline: none; border-color: var(--accent); }
.caperr { color: var(--red); font-size: .78rem; margin: .55rem 0 0; }
.capfoot { display: flex; justify-content: flex-end; gap: .5rem; margin-top: .9rem; }

/* ---------- server picker ---------- */

.glist { display: flex; flex-direction: column; gap: .4rem; margin-top: .8rem; }
.gpick {
  display: flex; align-items: center; gap: .8rem;
  padding: .65rem .8rem; border-radius: 10px;
  border: 1px solid var(--line); background: var(--panel2);
  color: var(--muted);
  transition: border-color .18s var(--ease), background .18s var(--ease), transform .18s var(--ease);
}
.gpick:hover { border-color: var(--line-hi); background: #1b1722; transform: translateX(2px); }
.gpick img, .gpick .ginit {
  width: 36px; height: 36px; border-radius: 10px; flex: 0 0 auto; object-fit: cover;
}
.gpick .ginit {
  display: grid; place-items: center; background: rgba(179,164,200,.12);
  color: #cdbfe4; font-size: .8rem; font-weight: 600;
}
.gpick .gtext { flex: 1; min-width: 0; }
.gpick .gtext strong { display: block; color: #fff; font-weight: 500; font-size: .93rem; }
.gpick .gtext span { display: block; color: var(--dim); font-size: .78rem; }
.gpick .garr { color: var(--dim); font-size: 1.2rem; }
.gpick.done { opacity: .82; }

/* The bar has a fixed brand, language chip and sign-in button, so the links
   are the only part that can give. Below 900px they drop to icons; below
   620px they go entirely and the page is navigated from the footer. */
/* ---------- page headers ---------- */

.pagehead {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 1.2rem; flex-wrap: wrap; margin-bottom: .2rem;
}
.bigtitle {
  font-size: clamp(2.2rem, 5vw, 3.1rem); letter-spacing: -.04em; margin: 0;
  background: linear-gradient(100deg, #fff 30%, var(--sakura) 70%, var(--plum));
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.submeta { font-size: .84rem; margin: .35rem 0 1.3rem; }
.headtools { display: flex; gap: .5rem; align-items: center; }

.searchbox {
  display: flex; align-items: center; gap: .38rem;
  background: rgba(255,255,255,.04); border: 1px solid rgba(255,255,255,.08);
  border-radius: 8px; padding: .3rem .55rem; min-width: 160px; max-width: 220px;
}
.searchbox svg { width: 12px; height: 12px; color: var(--dim); flex: 0 0 auto; }
.searchbox input {
  flex: 1; min-width: 0; background: none; border: 0; color: #fff;
  font: inherit; font-size: .74rem; line-height: 1.6; outline: none;
}
.searchbox input::placeholder { color: var(--dim); }

/* ---------- commands ---------- */

.catbar { position: relative; margin-bottom: 1.4rem; }
.catscroll {
  display: flex; gap: .35rem; overflow-x: auto; padding: .35rem;
  border: 1px solid rgba(255,255,255,.07); border-radius: 999px;
  background: rgba(255,255,255,.02); scrollbar-width: none;
}
.catscroll::-webkit-scrollbar { display: none; }
.catpill {
  display: inline-flex; align-items: center; gap: .4rem; white-space: nowrap;
  font: inherit; font-size: .83rem; font-weight: 500; cursor: pointer;
  color: var(--muted); background: transparent; border: 0;
  padding: .42rem .85rem; border-radius: 999px;
  transition: background .18s var(--ease), color .18s var(--ease);
}
.catpill span { color: var(--dim); font-size: .74rem; }
.catpill:hover { color: #fff; background: rgba(255,255,255,.05); }
.catpill.active { color: #fff; background: rgba(88,101,242,.2); }
.catpill.active span { color: #c9cdfb; }

.cmdwrap { display: grid; grid-template-columns: 200px minmax(0, 1fr); gap: 2.2rem; align-items: start; }
.catrail { position: sticky; top: 5rem; display: flex; flex-direction: column; gap: .1rem; }
.catrail button {
  display: flex; align-items: center; justify-content: space-between; gap: .6rem;
  font: inherit; font-size: .85rem; text-align: left; cursor: pointer;
  color: var(--dim); background: none; border: 0; border-left: 2px solid transparent;
  padding: .42rem .8rem; transition: color .2s var(--ease), border-color .2s var(--ease);
}
.catrail button b { font-weight: 500; }
.catrail button i { font-style: normal; font-size: .72rem; color: var(--dim); opacity: .8; }
.catrail button:hover { color: var(--muted); }
.catrail button.active { color: #fff; border-left-color: var(--sakura); }
.catrail button.active i { color: var(--sakura); }

.cmdgrid { display: flex; flex-direction: column; gap: .1rem; }
.cmdcard {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: .2rem 1rem;
  padding: .85rem 0; border-bottom: 1px solid rgba(255,255,255,.05);
  transition: background .2s var(--ease);
}
.cmdcard:hover { background: rgba(255,255,255,.018); }
.cmdtop { display: flex; align-items: center; gap: .6rem; grid-column: 1; }
.cmdtop h3 { margin: 0; font-size: .92rem; font-weight: 600; color: #fff; letter-spacing: -.01em; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.copybtn {
  flex: 0 0 auto; background: none; border: 1px solid transparent; color: var(--dim);
  border-radius: 7px; padding: .28rem; cursor: pointer; line-height: 0;
  transition: color .18s var(--ease), border-color .18s var(--ease), background .18s var(--ease);
}
.copybtn svg { width: 15px; height: 15px; }
.copybtn:hover { color: #fff; background: rgba(255,255,255,.06); border-color: rgba(255,255,255,.1); }
.copybtn.done { color: var(--green); }
.cmddesc { color: var(--muted); font-size: .83rem; line-height: 1.5; margin: .2rem 0 0; grid-column: 1; }
.cmdmeta { grid-column: 2; grid-row: 1 / span 2; align-self: center; }
.metalabel { display: none; }
.argrow { display: flex; flex-wrap: wrap; gap: .28rem; justify-content: flex-end; }
.argchip {
  background: rgba(255,255,255,.05); border: 1px solid rgba(255,255,255,.08);
  color: #d6cfe4; font-size: .74rem; padding: .18rem .5rem; border-radius: 6px;
}
.argchip.req { border-color: rgba(247,183,203,.35); color: #f7d3de; }
.argnone { color: var(--dim); font-size: .78rem; }
.usage { display: none; }
.copybtn { opacity: 0; }
.cmdcard:hover .copybtn, .copybtn:focus-visible, .copybtn.done { opacity: 1; }

@media (max-width: 860px) {
  .cmdwrap { grid-template-columns: 1fr; gap: 1rem; }
  .catrail { position: static; flex-direction: row; overflow-x: auto; padding-bottom: .3rem; }
  .catrail button { border-left: 0; border-bottom: 2px solid transparent; white-space: nowrap; }
  .catrail button.active { border-bottom-color: var(--sakura); }
  .cmdcard { grid-template-columns: 1fr; }
  .cmdmeta { grid-column: 1; grid-row: auto; margin-top: .4rem; }
  .argrow { justify-content: flex-start; }
  .copybtn { opacity: 1; }
}

/* ---------- status headline ---------- */

.bigstats { display: grid; gap: .9rem; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); margin: 1.2rem 0 1.5rem; }
.bstat {
  background: linear-gradient(180deg, rgba(255,255,255,.05), rgba(255,255,255,.012));
  border: 1px solid rgba(255,255,255,.08); border-radius: 14px; padding: 1.1rem 1.2rem;
}
.bk { display: block; color: var(--dim); font-size: .7rem; text-transform: uppercase; letter-spacing: .09em; font-weight: 500; }
.bv { display: block; font-size: 1.85rem; font-weight: 650; letter-spacing: -.035em; margin-top: .3rem; }

/* ---------- docs ---------- */

.eyebrow { color: var(--sakura); font-size: .76rem; font-weight: 600; letter-spacing: .05em; margin: 0 0 .2rem; }
.docsearch {
  display: flex; align-items: center; gap: .38rem; margin-bottom: 1.1rem;
  background: rgba(255,255,255,.04); border: 1px solid rgba(255,255,255,.08);
  border-radius: 8px; padding: .3rem .55rem;
}
.docsearch svg { width: 12px; height: 12px; color: var(--dim); flex: 0 0 auto; }
.docsearch input { flex: 1; min-width: 0; background: none; border: 0; color: #fff; font: inherit; font-size: .74rem; line-height: 1.6; outline: none; }
.docsearch input::placeholder { color: var(--dim); }

.docgroup { margin-bottom: 1.1rem; }
.docgrouph {
  color: #fff; font-size: .74rem; font-weight: 650; letter-spacing: .04em;
  text-transform: uppercase; margin: 0 0 .3rem; padding-left: .1rem;
}
.docgroup a { display: block; }

.stitle .row img {
  width: 30px; height: 30px; border-radius: 9px; display: block; flex: 0 0 auto;
}
.stitle .row { display: flex; align-items: center; gap: .6rem; }

.docsec { scroll-margin-top: 5.5rem; }
.docsec h3 { scroll-margin-top: 5.5rem; }

.docrail { position: sticky; top: 5rem; align-self: start; max-height: calc(100vh - 7rem); overflow-y: auto; scrollbar-width: none; }
.docrail::-webkit-scrollbar { width: 0; }
.railh { color: var(--dim); font-size: .7rem; text-transform: uppercase; letter-spacing: .08em; margin: 0 0 .5rem; }
.docrail a {
  display: block; color: var(--dim); font-size: .8rem; line-height: 1.45;
  padding: .24rem 0 .24rem .7rem; border-left: 1px solid var(--line);
  transition: color .2s var(--ease), border-color .2s var(--ease);
}
.docrail a:hover { color: #fff; }
.docrail a.railtop { color: #fff; border-left-color: var(--sakura); }

/* ---------- server picker grid ---------- */

/* The picker is its own page rather than a section of the setup page, so it
   gets a column of its own: narrower than the dashboard, centred, with the
   heading over the middle of the grid rather than off in the corner. */
/* One number for both halves of the dashboard: the picker's column and the
   settings column inside the rail. Declared on :root so the two stylesheets
   cannot drift apart. */
:root { --dash-col: 1180px; }
body.pickmode main.wide { max-width: calc(var(--dash-col) + 3rem); }
body.pickmode .pagehead {
  flex-direction: column; align-items: center; text-align: center;
  gap: .9rem; margin-bottom: 1.4rem;
}
body.pickmode .pagehead .headtools { width: 100%; max-width: 26rem; }
/* `max-width: none` matters as much as the width. The base .searchbox caps
   itself at 220px for the narrow headers it normally sits in, and a rule
   setting only `width: 100%` loses to that cap - which is why the picker's
   search box stayed stubbornly small inside a header several times wider. */
body.pickmode .searchbox { width: 100%; max-width: none; min-width: 0; }
body.pickmode .gsectionh { justify-content: center; }

/* The heading is left-aligned with a count beside it rather than centred
   between two rules. Centred section headings read as decoration; this one
   carries a number people actually check. */
.gsectionh {
  display: flex; align-items: center; gap: .55rem;
  color: var(--dim); font-size: .74rem; text-transform: uppercase; letter-spacing: .09em;
  font-weight: 600; margin: 2.2rem 0 1rem;
}
.gcount {
  display: inline-grid; place-items: center; min-width: 1.35rem; height: 1.35rem;
  padding: 0 .35rem; border-radius: 999px;
  background: rgba(255,255,255,.06); border: 1px solid var(--line);
  color: var(--text); font-size: .7rem; letter-spacing: 0; font-weight: 600;
}

/* Flex rather than grid, so a row that is not full centres itself instead of
   packing to the left with a gap on the right. A grid cannot do that: its
   columns exist whether or not anything is in them. */
.ggrid3 {
  display: flex; flex-wrap: wrap; gap: 1.1rem; justify-content: center;
}
.ggrid3 > * { flex: 1 1 330px; max-width: 420px; min-width: 280px; }

/* Portrait, and everything inside it centred on one axis, so a grid of these
   is scanned down a column instead of read row by row. */
.gcard3 {
  /* `contain: paint` keeps the blurred artwork's repaints inside the card.
     Without it a grid of thirty blurred backgrounds is one enormous paint
     region, and scrolling past them costs a frame each time. */
  contain: paint;
  position: relative; overflow: hidden; border-radius: 16px;
  border: 1px solid rgba(255,255,255,.07);
  background: rgba(255,255,255,.02);
  transition: border-color .3s var(--ease), transform .3s var(--ease);
}
.gcard3:hover { border-color: rgba(247,183,203,.3); transform: translateY(-2px); }

.gcart {
  position: absolute; inset: 0;
  background-size: cover; background-position: center;
  filter: blur(20px) saturate(1.2); opacity: .3; transform: scale(1.3);
}
/* A real banner is already wide art, so it needs far less blur than a
   64px icon stretched to fill the card. */
.gcart.banner { filter: blur(10px) saturate(1.1); opacity: .38; transform: scale(1.1); }
.gcart.plain { background: linear-gradient(140deg, rgba(179,164,200,.18), rgba(88,101,242,.12)); filter: none; transform: none; }
.gcard3::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(10,10,10,.45), rgba(10,10,10,.9));
}

.gcbody {
  position: relative; z-index: 1;
  display: flex; flex-direction: column; align-items: center; gap: .55rem;
  padding: 1.7rem 1.2rem 1.2rem;
}
.gcicon {
  width: 64px; height: 64px; border-radius: 50%; object-fit: cover; background: #1e1f22;
  border: 1px solid rgba(255,255,255,.09);
}
.gcicon.blank {
  display: grid; place-items: center; background: rgba(179,164,200,.18);
  color: #e6dff2; font-size: 1rem; font-weight: 600;
}
/* width rather than max-width: the card is a centred flex column, so the name
   is sized to its own content and a max-width never binds. A long server name
   ran straight out past the card edge. */
.gcname {
  display: block; width: 100%; min-width: 0; color: #fff; font-size: .97rem; font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-align: center;
}
.gcrole {
  display: inline-flex; align-items: center; gap: .28rem;
  font-size: .68rem; font-weight: 600; letter-spacing: .02em;
  color: var(--dim); background: rgba(255,255,255,.05);
  border: 1px solid var(--line); border-radius: 999px; padding: .16rem .55rem;
}
.gcrole svg { width: 11px; height: 11px; }
.gcrole.owner { color: #cdd2fb; background: rgba(88,101,242,.16); border-color: rgba(88,101,242,.34); }

.gcbtn {
  width: 100%; margin-top: .35rem;
  display: inline-flex; align-items: center; justify-content: center; gap: .35rem;
  font: inherit; font-size: .8rem; font-weight: 500; cursor: pointer; text-decoration: none;
  color: var(--text); background: rgba(255,255,255,.05); border: 1px solid var(--line);
  padding: .5rem .7rem; border-radius: 10px;
  transition: background .18s var(--ease), color .18s var(--ease), border-color .18s var(--ease);
}
.gcbtn svg { width: 13px; height: 13px; }
.gcbtn:hover { background: rgba(255,255,255,.09); border-color: var(--line-hi); color: #fff; }
.gcbtn.on { background: rgba(127,209,196,.16); border-color: rgba(127,209,196,.34); color: #bdeee6; }
.gcbtn.on:hover { background: rgba(127,209,196,.28); color: #fff; }

.gnone { text-align: center; margin: 2.5rem 0; font-size: .88rem; }

/* ---------- account menu ---------- */

.acct { position: relative; display: flex; align-items: center; flex: 0 0 auto; }
.acctbtn {
  display: inline-flex; align-items: center; gap: .3rem; cursor: pointer;
  background: var(--panel); border: 1px solid var(--line); border-radius: 999px;
  padding: .22rem .5rem .22rem .22rem; font: inherit; color: var(--muted);
  transition: border-color .2s var(--ease), background .2s var(--ease);
}
.acctbtn:hover { border-color: var(--line-hi); color: #fff; }
.acctbtn img, .acctfall { width: 26px; height: 26px; border-radius: 50%; display: block; object-fit: cover; background: rgba(179,164,200,.2); flex: 0 0 auto; }

/* Collapsed to the avatar until hovered. A username in the nav costs space
   the links want more, and it is the same name on every page. No chevron:
   the row lights up on hover, which says it does something. */
.acctname {
  max-width: 0; opacity: 0; overflow: hidden; white-space: nowrap;
  font-size: .82rem; font-weight: 500;
  transition: max-width .26s var(--ease), opacity .2s var(--ease);
}
.acctbtn:hover .acctname,
.acctbtn:focus-visible .acctname,
.acct.open .acctname { max-width: 10rem; opacity: 1; }

.acctmenu {
  position: absolute; right: 0; top: calc(100% + .5rem); min-width: 210px;
  background: var(--panel-solid); border: 1px solid var(--line-hi); border-radius: 13px;
  padding: .4rem; box-shadow: var(--shadow); z-index: 60;
  animation: fadeUp .2s var(--ease) both;
}
.acctwho { display: flex; align-items: center; gap: .55rem; padding: .5rem .55rem .6rem; border-bottom: 1px solid var(--line); margin-bottom: .35rem; }
.acctwho img { width: 32px; height: 32px; border-radius: 50%; object-fit: cover; }
.acctwho strong { display: block; color: #fff; font-size: .86rem; font-weight: 600; }
.acctmenu a, .acctout {
  display: block; width: 100%; text-align: left; font: inherit; font-size: .85rem;
  color: var(--muted); background: none; border: 0; cursor: pointer;
  padding: .5rem .55rem; border-radius: 8px;
  transition: background .16s var(--ease), color .16s var(--ease);
}
.acctmenu a { display: flex; align-items: center; gap: .5rem; }
.acctmenu a svg { width: 14px; height: 14px; flex: 0 0 auto; opacity: .6; }
.acctmenu a:hover, .acctout:hover { background: rgba(255,255,255,.06); color: #fff; }
.acctmenu a:hover svg { opacity: 1; }
/* The owner entry only exists for one person, so it is allowed to stand out. */
.acctowner { color: var(--sakura) !important; }
.acctowner svg { opacity: 1 !important; color: var(--sakura); }
.acctowner:hover { background: rgba(247,183,203,.12) !important; }

/* Expired owner session: visible, and obviously an action rather than a link. */
.acctexpired {
  display: flex; align-items: center; gap: .5rem; width: 100%; text-align: left;
  font: inherit; font-size: .78rem; line-height: 1.35; cursor: pointer;
  color: var(--amber); background: rgba(251,191,36,.08);
  border: 1px solid rgba(251,191,36,.22); border-radius: 8px;
  padding: .5rem .55rem; margin-top: .15rem;
}
.acctexpired svg { width: 14px; height: 14px; flex: 0 0 auto; }
.acctexpired:hover { background: rgba(251,191,36,.16); }
.acctout { color: var(--red); }
.acctout:hover { background: rgba(248,113,113,.12); color: var(--red); }

@media (max-width: 620px) {
  .pagehead { flex-direction: column; align-items: stretch; }
  .searchbox { min-width: 0; }
  .cmdgrid { grid-template-columns: 1fr; }
  .ggrid3 { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
  .docrail { display: none; }
}

@media (max-width: 900px) {
  nav.top .inner { gap: .5rem; }
  nav.top .links { margin-left: .2rem; min-width: 0; }
  nav.top .links a { padding: .5rem .55rem; }
  nav.top .links a span { display: none; }
  nav.top .links a svg { width: 17px; height: 17px; }
  .navind { display: none; }
}

@media (max-width: 620px) {
  nav.top .links { display: none; }
  .langbtn .flag { display: none; }
  body .petals { animation: none; }
  h1 { font-size: clamp(2rem, 9vw, 2.6rem); }
  .cta { flex-direction: column; align-items: stretch; }
  .cta .btn { justify-content: center; width: 100%; }
  .grid { grid-template-columns: 1fr; }
  .features { grid-template-columns: 1fr; }
  .panel { padding: 1.15rem; }
  .doctable { font-size: .82rem; }
  .doctable th, .doctable td { padding: .5rem .45rem; }
  .tstable { font-size: .8rem; }
  .estage { padding: .7rem .5rem; min-height: 0; }
  .dembed, .drow { max-width: 100%; }
  .dthumb { width: 46px; height: 46px; }
  .dfield.inline { flex: 1 1 44%; }
  .vlogo { width: 52px; height: 52px; }
  section[style*="margin-top:5rem"] { margin-top: 3rem !important; }
}

/* Tables are the one thing that cannot reflow, so let them scroll
   inside their own box rather than widening the page. */
@media (max-width: 760px) {
  .doctable, .tstable { display: block; overflow-x: auto; white-space: nowrap; }
  main, .doccontent { overflow-x: hidden; }
}

@media (max-width: 760px) {
  nav.top .inner { gap: .5rem; padding: .55rem .8rem; min-height: 52px; }
  nav.top .brand img { width: 28px; height: 28px; }
  nav.top .brand span { display: none; }
  .btn.small, .langbtn { white-space: nowrap; }
  .me > span { max-width: 90px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  main { padding: 2.5rem 1rem 3.5rem; }
}

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

/* Marks a command added in the last week. Deliberately quiet: it should catch
   the eye while scanning without shouting over the command name itself. */
.newtag {
  display: inline-block;
  margin-left: .55rem;
  padding: .12rem .42rem;
  border-radius: 999px;
  font-size: .62em;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  vertical-align: middle;
  color: #7ee787;
  background: rgba(126, 231, 135, .12);
  border: 1px solid rgba(126, 231, 135, .28);
}

/* What a command needs before it will run. Quieter than the argument chips,
   since it is a caveat rather than something you type. */
.needrow {
  grid-column: 1;
  display: flex;
  flex-wrap: wrap;
  gap: .3rem;
  margin-top: .45rem;
}
.needchip {
  font-size: .7rem;
  letter-spacing: .01em;
  padding: .16rem .48rem;
  border-radius: 999px;
  color: var(--dim);
  background: rgba(255,255,255,.03);
  border: 1px solid rgba(255,255,255,.07);
}
.needchip.perm {
  color: #f7d3de;
  background: rgba(247,183,203,.08);
  border-color: rgba(247,183,203,.24);
}

/* ---- hero reach line ---- */

/* The figures read as a sentence rather than a scoreboard. A grid of boxes
   would be the status page repeated, which tells a visitor nothing new. */
.reach {
  margin: 1.9rem 0 0;
  color: var(--muted);
  font-size: 1.02rem;
  opacity: 0;
  transform: translateY(6px);
  transition: opacity .6s var(--ease), transform .6s var(--ease);
}
.reach.on { opacity: 1; transform: none; }
.reach b {
  color: var(--text);
  font-weight: 700;
  /* Tabular figures so a counting number does not shuffle the words around it. */
  font-variant-numeric: tabular-nums;
}

/* ---- the seam under the hero ---- */

.seam {
  position: relative;
  height: 150px;
  margin: -1rem 0 .5rem;
  pointer-events: none;
}
.seam svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* Softens the stack into one ribbon instead of eleven countable lines. */
  filter: blur(.4px);
}

.motes { position: absolute; inset: 0; overflow: hidden; }
.motes span {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: var(--size);
  height: var(--size);
  border-radius: 50%;
  background: var(--sakura);
  opacity: var(--opacity);
  box-shadow: 0 0 6px 1px color-mix(in srgb, var(--sakura) 45%, transparent);
  animation: drift var(--dur) var(--delay) infinite ease-in-out alternate;
}

@keyframes drift {
  from { transform: translate(0, 0); }
  to   { transform: translate(var(--dx), var(--dy)); }
}

@media (prefers-reduced-motion: reduce) {
  .motes { display: none; }
  .reach { opacity: 1; transform: none; transition: none; }
}

/* ---- platform cards: lift and glow in their own colour ---- */

.plat::after {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  background: radial-gradient(120% 80% at 50% 120%, currentColor, transparent 65%);
  opacity: 0;
  transition: opacity .3s var(--ease);
  pointer-events: none;
}
.plat:hover::after { opacity: .16; }
.plat:hover {
  border-color: color-mix(in srgb, currentColor 40%, var(--line));
  box-shadow: 0 8px 26px -12px color-mix(in srgb, currentColor 55%, transparent);
}
.plat:hover .plogo {
  background: color-mix(in srgb, currentColor 26%, transparent);
  border-color: color-mix(in srgb, currentColor 45%, transparent);
}

/* ---- nav condenses to icons once you scroll ---- */

/* The bar is a full menu at the top of the page where there is room for it,
   and shrinks to its icons on the way down where it is only ever in the way.
   Width is animated rather than display toggled so it collapses rather than
   snapping, and the labels keep their title and aria-label so the bar is no
   less usable once the words have gone. */
nav.top .links a span {
  display: inline-block;
  max-width: 12rem;
  overflow: hidden;
  white-space: nowrap;
  opacity: 1;
  transition: max-width .32s var(--ease), opacity .18s var(--ease), margin .32s var(--ease);
}
nav.top.scrolled .links a span {
  max-width: 0;
  opacity: 0;
  margin-left: -.35rem;
}
nav.top.scrolled .links a { padding-left: .62rem; padding-right: .62rem; }
nav.top.scrolled .navind { opacity: 0; }

/* The moving indicator is measured from the label widths, so it is wrong the
   moment they collapse. Hidden rather than recalculated: at icon width the
   active state reads from the icon itself. */
nav.top .navind { transition: opacity .2s var(--ease), transform .3s var(--ease), width .3s var(--ease); }

@media (prefers-reduced-motion: reduce) {
  nav.top .links a span,
  nav.top .navind { transition: none; }
}

/* ---- feature grid ---- */

/* The dashboard's grid, which the landing page used to share. Kept exactly as
   it was: it is declared after the narrower .fgrid higher up, so this is the
   one every settings panel has actually been using. */
.fgrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(255px, 1fr));
  gap: 1rem;
  margin-top: 2rem;
}

/* ---- landing page sections ----

   These used to be bordered cards holding a bordered icon tile: a box inside a
   box, eight times over, which read as a form rather than a page. The frame is
   gone and the spacing does the separating instead, so the words are the thing
   you see. The dashboard keeps .fgrid, which is a different grid on a screen
   that genuinely is a form. */

.sechead { text-align: center; max-width: 62ch; margin: 0 auto 3rem; }

.sechead .sbadge {
  display: grid; place-items: center;
  width: 62px; height: 62px; margin: 0 auto 1.5rem;
  border-radius: 18px;
  background: color-mix(in srgb, var(--sakura) 9%, transparent);
  border: 1px solid color-mix(in srgb, var(--sakura) 18%, transparent);
  color: var(--sakura);
}
.sechead .sbadge svg { width: 26px; height: 26px; }

.sechead h2 {
  font-size: clamp(1.9rem, 4.2vw, 2.9rem);
  line-height: 1.12;
  letter-spacing: -.025em;
  margin: 0 0 .9rem;
}
.sechead p { color: var(--muted); font-size: 1.02rem; line-height: 1.6; margin: 0 auto; max-width: 52ch; }

.featgrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 2.6rem 2.2rem;
  margin-top: 3.2rem;
}

.fcard {
  display: block;
  text-decoration: none;
  color: inherit;
  transition: color .2s var(--ease);
}
.ficon {
  display: block;
  margin-bottom: .95rem;
  color: var(--sakura);
  transition: color .2s var(--ease), transform .2s var(--ease);
}
.ficon svg { width: 24px; height: 24px; }
.fcard b {
  display: block; margin-bottom: .45rem;
  font-size: 1.06rem; letter-spacing: -.01em;
}
.fdesc { display: block; color: var(--muted); font-size: .92rem; line-height: 1.6; }

.fcard:hover .ficon { color: var(--cream); transform: translateY(-2px); }
.fcard:hover b { color: var(--sakura); }

@media (prefers-reduced-motion: reduce) {
  .fcard, .fcard:hover, .ficon { transition: none; transform: none; }
}
}

/* ---- embed builder ---- */

.eb-bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap; margin: 2rem 0 1.2rem;
}
.eb-modes { display: flex; gap: .4rem; background: var(--panel2); border: 1px solid var(--line); border-radius: 12px; padding: .3rem; }
.eb-mode {
  display: inline-flex; align-items: center; gap: .45rem;
  background: none; border: 0; color: var(--muted); font: inherit; font-size: .88rem; font-weight: 600;
  padding: .45rem .8rem; border-radius: 9px; cursor: pointer;
  transition: background .18s var(--ease), color .18s var(--ease);
}
.eb-mode svg { width: 15px; height: 15px; }
.eb-mode:hover { color: #fff; }
.eb-mode.active { background: rgba(88,101,242,.16); color: #fff; }
.eb-count { color: var(--dim); font-size: .8rem; }

.eb-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr); gap: 1.4rem; align-items: start; }
@media (max-width: 900px) { .eb-grid { grid-template-columns: 1fr; } }

.eb-side { position: sticky; top: 5rem; display: grid; gap: 1rem; }
@media (max-width: 900px) { .eb-side { position: static; } }

.eb-edit { display: grid; gap: 1rem; }
.eb-block { padding: 1rem 1.1rem; }
.eb-label {
  display: flex; align-items: center; justify-content: space-between; gap: .6rem;
  color: var(--dim); font-size: .72rem; font-weight: 700;
  letter-spacing: .09em; text-transform: uppercase; margin-bottom: .8rem;
}
.eb-field { display: block; margin-bottom: .7rem; }
.eb-field .flabel { display: block; margin-bottom: .28rem; }
.eb-field input, .eb-field textarea, .eb-field select {
  width: 100%; background: var(--bg); border: 1px solid var(--line);
  border-radius: 9px; padding: .5rem .65rem; color: var(--text);
  font: inherit; font-size: .87rem; transition: border-color .18s var(--ease);
}
.eb-field input:focus, .eb-field textarea:focus, .eb-field select:focus {
  outline: none; border-color: var(--line-hi);
}
.eb-field input[type="color"] { padding: .2rem; height: 38px; cursor: pointer; }
.eb-field textarea { resize: vertical; line-height: 1.5; }
.eb-row { display: grid; grid-template-columns: 1fr 1fr; gap: .6rem; }

.eb-toggle { display: inline-flex; align-items: center; gap: .35rem; color: var(--muted); font-size: .78rem; text-transform: none; letter-spacing: 0; font-weight: 500; }

.eb-sub { border: 1px solid var(--line); border-radius: 10px; padding: .7rem .8rem; margin-bottom: .6rem; background: rgba(255,255,255,.012); }
.eb-subhead { display: flex; align-items: center; justify-content: space-between; gap: .5rem; margin-bottom: .55rem; color: var(--muted); font-size: .8rem; font-weight: 600; }
.eb-moves { display: inline-flex; gap: .25rem; }
.eb-x {
  background: none; border: 1px solid var(--line); color: var(--dim);
  border-radius: 7px; width: 24px; height: 24px; line-height: 1; cursor: pointer;
  font-size: .85rem; transition: color .15s var(--ease), border-color .15s var(--ease);
}
.eb-x:hover:not(:disabled) { color: #fff; border-color: var(--line-hi); }
.eb-x:disabled { opacity: .35; cursor: default; }

.eb-add { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: .5rem; }
.eb-addbtn {
  display: flex; flex-direction: column; gap: .12rem; text-align: left;
  background: var(--bg); border: 1px solid var(--line); border-radius: 10px;
  padding: .6rem .7rem; cursor: pointer; font: inherit; color: var(--text);
  transition: border-color .18s var(--ease), background .18s var(--ease);
}
.eb-addbtn:hover { border-color: var(--line-hi); background: rgba(179,164,200,.06); }
.eb-addbtn b { font-size: .86rem; font-weight: 600; }
.eb-addbtn span { font-size: .74rem; color: var(--dim); }

.eb-preview { padding: 1rem 1.1rem; }
.eb-script { padding: 1rem 1.1rem; }
.eb-code {
  margin: 0; background: var(--bg); border: 1px solid var(--line); border-radius: 10px;
  padding: .75rem .85rem; color: #cdbfe4; font-size: .8rem; line-height: 1.6;
  white-space: pre-wrap; word-break: break-word; max-height: 260px; overflow: auto;
}

/* ---- classic embed, as Discord draws it ---- */

.e-embed {
  display: flex; gap: 1rem; align-items: flex-start;
  background: #2b2d31; border-left: 4px solid var(--e-accent, #B3A4C8);
  border-radius: 4px; padding: .7rem .9rem; margin-top: .3rem; max-width: 520px;
}
.e-body { flex: 1; min-width: 0; }
.e-author { display: flex; align-items: center; gap: .4rem; color: #f2f3f5; font-size: .82rem; font-weight: 600; margin-bottom: .25rem; }
.e-author img { width: 20px; height: 20px; border-radius: 50%; object-fit: cover; }
.e-title { color: #00a8fc; font-weight: 600; font-size: .95rem; margin-bottom: .25rem; }
.e-title a { color: inherit; text-decoration: none; }
.e-title a:hover { text-decoration: underline; }
.e-desc { color: #dbdee1; font-size: .86rem; line-height: 1.45; }
.e-image { width: 100%; border-radius: 4px; margin-top: .5rem; display: block; }
.e-thumb { width: 74px; height: 74px; border-radius: 4px; object-fit: cover; flex: 0 0 auto; }
.e-footer { display: flex; align-items: center; gap: .4rem; color: #b5bac1; font-size: .74rem; margin-top: .5rem; }
.e-footer img { width: 18px; height: 18px; border-radius: 50%; object-fit: cover; }
.e-empty { color: var(--dim); font-size: .84rem; }

.c-gallery { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: .25rem; margin-top: .4rem; max-width: 520px; }
.c-gallery img { width: 100%; border-radius: 4px; display: block; object-fit: cover; }
.c-h1 { color: #f2f3f5; font-size: 1.1rem; font-weight: 700; margin: .2rem 0; }
.c-h2 { color: #f2f3f5; font-size: 1rem; font-weight: 700; margin: .2rem 0; }
.c-h3 { color: #f2f3f5; font-size: .92rem; font-weight: 600; margin: .2rem 0; }
.c-sub { color: #949ba4; font-size: .78rem; }
.c-code { background: #1e1f22; border: 1px solid #2b2d31; border-radius: 4px; padding: .5rem .6rem; color: #dbdee1; font-size: .78rem; overflow-x: auto; }

/* ---- server dashboard shell ---- */

.dash { display: grid; grid-template-columns: 250px minmax(0, 1fr); gap: 1.6rem; align-items: start; }
@media (max-width: 900px) { .dash { grid-template-columns: 1fr; } }

.dash-rail {
  position: sticky; top: 5rem; background: var(--panel-solid);
  border: 1px solid var(--line); border-radius: 16px; padding: .8rem;
}
@media (max-width: 900px) { .dash-rail { position: static; } }

/* The whole row is the control. Aiming at a 16px chevron to change server,
   with the row naming the current one sitting right beside it doing nothing,
   was the awkward part. */
.dash-server {
  width: 100%; display: flex; align-items: center; gap: .6rem;
  padding: .55rem .6rem; border: 1px solid var(--line); border-radius: 12px;
  background: var(--panel2); margin-bottom: .9rem;
  color: inherit; font: inherit; text-align: left; cursor: pointer;
  transition: border-color .15s var(--ease), background .15s var(--ease);
}
.dash-server:hover { border-color: var(--line-hi); background: rgba(255, 255, 255, .035); }
.dash-server[aria-expanded="true"] { border-color: var(--accent); }
.dash-server[aria-expanded="true"] .dash-switch { color: #fff; }
.dash-server img, .dash-badge {
  width: 34px; height: 34px; border-radius: 10px; flex: 0 0 auto; object-fit: cover;
}
.dash-badge { display: grid; place-items: center; background: rgba(179,164,200,.16); color: var(--accent); font-weight: 700; }
.dash-servertext { min-width: 0; flex: 1; display: flex; flex-direction: column; line-height: 1.25; }
.dash-servertext .dim { font-size: .68rem; }
.dash-servertext strong { font-size: .88rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dash-switch {
  color: var(--dim); padding: .2rem; flex: 0 0 auto;
  display: grid; place-items: center; transition: color .15s var(--ease);
}
.dash-server:hover .dash-switch { color: #fff; }
.dash-switch svg { width: 16px; height: 16px; }

/* ---- server dropdown ---- */

.srv-list { max-height: 300px; overflow-y: auto; padding: .35rem; }
.srv-opt {
  width: 100%; display: flex; align-items: center; gap: .55rem;
  padding: .4rem .5rem; border: 0; border-radius: 9px; background: none;
  color: var(--muted); font: inherit; font-size: .85rem; text-align: left; cursor: pointer;
}
.srv-opt img, .srv-opt .dash-badge {
  width: 24px; height: 24px; border-radius: 7px; flex: 0 0 auto; object-fit: cover; font-size: .7rem;
}
.srv-opt span {
  flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.srv-opt:hover { background: rgba(255, 255, 255, .055); color: var(--text); }
.srv-opt.on { color: var(--text); font-weight: 600; }
.srv-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); flex: 0 0 auto; }

/* The way out to the full list, kept as a footer rather than a row in the
   list itself so it cannot be hit while skimming servers. */
.srv-all {
  width: 100%; display: flex; align-items: center; gap: .5rem;
  padding: .6rem .75rem; border: 0; border-top: 1px solid var(--line);
  background: none; color: var(--dim); font: inherit; font-size: .8rem;
  text-align: left; cursor: pointer; transition: color .15s var(--ease);
}
.srv-all:hover { color: var(--text); }
.srv-all svg { width: 14px; height: 14px; flex: 0 0 auto; }

.dash-group {
  color: var(--dim); font-size: .66rem; font-weight: 700; letter-spacing: .11em;
  text-transform: uppercase; padding: .8rem .6rem .35rem;
}
.dash-nav { display: flex; flex-direction: column; gap: .12rem; }
.dash-item {
  display: flex; align-items: center; gap: .6rem; width: 100%; text-align: left;
  background: none; border: 0; color: var(--muted); font: inherit; font-size: .88rem;
  padding: .5rem .6rem; border-radius: 10px; cursor: pointer;
  transition: background .16s var(--ease), color .16s var(--ease);
}
.dash-item svg { width: 17px; height: 17px; flex: 0 0 auto; opacity: .8; }
.dash-item:hover { background: rgba(255,255,255,.035); color: #fff; }
.dash-item.active { background: rgba(88,101,242,.16); color: #fff; }
.dash-item.active svg { opacity: 1; color: var(--accent); }

.dash-main { min-width: 0; }
.dash-crumb { display: flex; align-items: center; gap: .5rem; color: var(--dim); font-size: .8rem; margin-bottom: 1.2rem; }
.dash-crumb b { color: var(--text); font-weight: 600; }
.dash-sep { opacity: .5; }

.dash-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; flex-wrap: wrap; margin-bottom: 1.4rem; }
.dash-hi { font-size: 1.35rem; margin: 0; letter-spacing: -.02em; }
.dash-ranges { display: flex; gap: .2rem; background: var(--panel2); border: 1px solid var(--line); border-radius: 10px; padding: .22rem; }
.dash-range {
  background: none; border: 0; color: var(--muted); font: inherit; font-size: .8rem; font-weight: 600;
  padding: .35rem .7rem; border-radius: 8px; cursor: pointer; transition: background .16s var(--ease), color .16s var(--ease);
}
.dash-range:hover { color: #fff; }
.dash-range.active { background: rgba(255,255,255,.07); color: #fff; }

/* Four across wherever there is room. auto-fit with a 180px floor dropped the
   fourth tile onto its own row inside the shell's narrower column, which read
   as one metric being singled out. */
.dash-tiles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: .7rem; margin-bottom: .8rem; }
@media (max-width: 1100px) { .dash-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 520px) { .dash-tiles { grid-template-columns: 1fr; } }
.dash-tile { padding: .75rem .9rem; }
.dash-tilehead { display: flex; align-items: center; justify-content: space-between; gap: .6rem; color: var(--muted); font-size: .83rem; }
.dash-tilenum { font-size: 1.55rem; font-weight: 700; letter-spacing: -.02em; margin-top: .25rem; }
.dash-delta { font-size: .72rem; font-weight: 600; padding: .16rem .42rem; border-radius: 999px; white-space: nowrap; }
.dash-delta.up { color: var(--green); background: rgba(110,231,168,.12); }
.dash-delta.down { color: var(--red); background: rgba(248,113,113,.12); }
.dash-delta.flat { color: var(--dim); background: rgba(255,255,255,.05); }

.dash-pulse { padding: .85rem 1rem; margin-bottom: .8rem; }
.dash-pulsehead { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; flex-wrap: wrap; margin-bottom: .6rem; }
.dash-pulsehead h3 { margin: 0; font-size: 1rem; }
.dash-toggle { display: flex; gap: .2rem; background: var(--panel2); border: 1px solid var(--line); border-radius: 10px; padding: .22rem; }
.dash-toggle button {
  background: none; border: 0; color: var(--muted); font: inherit; font-size: .78rem; font-weight: 600;
  padding: .34rem .66rem; border-radius: 8px; cursor: pointer; transition: background .16s var(--ease), color .16s var(--ease);
}
.dash-toggle button:hover { color: #fff; }
.dash-toggle button.active { background: rgba(255,255,255,.07); color: #fff; }
.dash-chart svg { width: 100%; height: 132px; display: block; }
.dash-axis { display: flex; justify-content: space-between; gap: 1rem; color: var(--dim); font-size: .72rem; margin-top: .5rem; }

/* 380px floor, not 300: four columns of numbers need the room, and side by
   side at 300 each the headers were being ellipsised down to "CHA...". Below
   that they stack, which is better than truncating the column the reader came
   for. */
/* 300px rather than 380: the old minimum meant the two tables only sat
   side by side on a very wide screen, and stacked into two full-width blocks
   everywhere else - which is most of the page's height on a quiet server. */
.dash-tables { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: .7rem; }
.dash-table { padding: 1.1rem 1.2rem; }
.dash-table h3 { margin: 0; font-size: .98rem; }
.dash-table table { width: 100%; border-collapse: collapse; }
.dash-table th {
  text-align: left; color: var(--dim); font-size: .7rem; font-weight: 700;
  letter-spacing: .07em; text-transform: uppercase; padding: .4rem .5rem; border-bottom: 1px solid var(--line);
}
.dash-table td { padding: .5rem .5rem; font-size: .85rem; border-bottom: 1px solid var(--line); }
.dash-table tr:last-child td { border-bottom: 0; }
.dash-ch { color: var(--text); font-weight: 500; }
.dash-bar {
  display: inline-block; width: 68px; height: 5px; border-radius: 3px;
  background: var(--panel2); overflow: hidden; vertical-align: middle; margin-right: .45rem;
}
.dash-bar i { display: block; height: 100%; background: var(--accent); border-radius: 3px; }

/* ---- dashboard rail chrome ---- */

.dash-railtop { display: flex; align-items: center; gap: .55rem; padding: .3rem .35rem .8rem; }
.dash-mark { width: 26px; height: 26px; border-radius: 8px; object-fit: cover; }
.dash-railtop b { flex: 1; font-size: .98rem; letter-spacing: -.01em; }
.dash-collapse {
  background: none; border: 0; color: var(--dim); cursor: pointer; padding: .2rem;
  display: grid; place-items: center; border-radius: 7px; transition: color .15s var(--ease), background .15s var(--ease);
}
.dash-collapse:hover { color: #fff; background: rgba(255,255,255,.05); }
.dash-collapse svg { width: 16px; height: 16px; transition: transform .22s var(--ease); }

/* No border. The fixed footer is already visually separate from the
   scrolling nav above it, and a rule there reads as the start of another
   panel rather than as the end of this one. */
.dash-railfoot { margin-top: .7rem; padding-top: .2rem; }
.dash-me { display: flex; align-items: center; gap: .5rem; color: var(--muted); font-size: .82rem; padding: .35rem .4rem; }
.dash-me img, .dash-badge.sm { width: 26px; height: 26px; border-radius: 50%; object-fit: cover; }
.dash-badge.sm { font-size: .8rem; }

/* Collapsed: icons only, so the rail becomes a strip without reflowing the
   page around it. */
.dash.collapsed { grid-template-columns: 68px minmax(0, 1fr); }
.dash.collapsed .dash-railtop b,
.dash.collapsed .dash-servertext,
.dash.collapsed .dash-switch,
.dash.collapsed .dash-group,
.dash.collapsed .dash-item span,
.dash.collapsed .dash-me span { display: none; }
.dash.collapsed .dash-item { justify-content: center; padding: .55rem 0; }
.dash.collapsed .dash-server { justify-content: center; padding: .45rem; }
.dash.collapsed .dash-railtop { justify-content: center; }
.dash.collapsed .dash-collapse svg { transform: rotate(180deg); }
.dash.collapsed .dash-me { justify-content: center; }
@media (max-width: 900px) { .dash.collapsed { grid-template-columns: 1fr; } }

.dash-crumb b { display: inline-flex; align-items: center; gap: .38rem; }
.dash-crumb b svg { width: 15px; height: 15px; opacity: .85; }

.dash-tilelabel { display: inline-flex; align-items: center; gap: .42rem; }
.dash-tilelabel svg { width: 15px; height: 15px; opacity: .75; }

.dash-legend { display: flex; justify-content: flex-end; gap: .9rem; margin: -.4rem 0 .5rem; }
.dash-key { display: inline-flex; align-items: center; gap: .35rem; color: var(--dim); font-size: .74rem; }
.dash-key i { width: 8px; height: 8px; border-radius: 50%; background: var(--line-hi); display: inline-block; }
.dash-key.on { color: var(--muted); }
.dash-key.on i { background: var(--accent); }

/* Labels on one line. Wrapping "Voice time" and "New members" made those two
   tiles taller than the others, which read as them being different in kind. */
.dash-tilehead { align-items: flex-start; }
.dash-tilelabel { white-space: nowrap; font-size: .8rem; }
/* Compact. The tile holds a label and a number, and 118px of height for
   that leaves a band of empty panel under every one - most noticeable on a
   quiet server, where all four read zero. */
.dash-tile { display: flex; flex-direction: column; justify-content: space-between; min-height: 84px; }
/* Four columns have to fit the panel, not scroll inside it. The bar shrinks,
   the channel name truncates, and the numbers stay whole - a scrollbar that
   hides the Change column defeats the point of having one. */
.dash-table table { width: 100%; table-layout: fixed; }
.dash-table th, .dash-table td { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dash-table th:nth-child(1), .dash-table td:nth-child(1) { width: 40%; }
.dash-table th:nth-child(2), .dash-table td:nth-child(2) { width: 20%; }
.dash-table th:nth-child(3), .dash-table td:nth-child(3) { width: 16%; }
.dash-table th:nth-child(4), .dash-table td:nth-child(4) { width: 24%; text-align: right; }

/* ---- security check ---- */

/* A doorway, not a destination. Everything on this page exists to sit still
   behind the one control that matters: a dot grid that breathes rather than a
   flat wash, and a card whose edge is drawn twice so it reads as a raised
   plate instead of a rectangle with a line around it. */
.vfbody {
  display: grid; place-items: center;
  min-height: 100vh; padding: 2rem 1.2rem;
  background: #08070a;
  overflow: hidden;
}
/* The site's colour wash and star field are switched off here. They belong on
   pages you are meant to look at; on this one they only sit between the eye
   and the widget, and the wash in particular drowns the grid that replaces
   them. */
.vfbody::before, .vfbody::after { display: none; }

/* Its own element rather than a background on the body. The mask and the
   animation both want to act on the grid alone, and putting them on the body
   drags the card's stacking context along with them. */
.vf-grid {
  position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background-image: radial-gradient(circle at 2px 2px, var(--accent) 1.4px, transparent 0);
  background-size: 34px 34px;
  -webkit-mask-image: radial-gradient(circle at center, #000 35%, transparent 70%);
  mask-image: radial-gradient(circle at center, #000 35%, transparent 70%);
  animation: vfPulse 3s ease-in-out infinite;
}
@keyframes vfPulse { 0%, 100% { opacity: .1 } 50% { opacity: .28 } }

/* padding:0 undoes the site-wide main padding. Left alone it took 1.5rem off
   each side of the card, which pulled the inner width below the 300px the
   Turnstile widget wants and squeezed the widget. */
.vfwrap {
  position: relative; z-index: 1;
  width: 100%; max-width: 380px; padding: 0;
  animation: vfIn .5s ease forwards;
}
@keyframes vfIn { from { opacity: 0 } to { opacity: 1 } }

/* The wordmark, with an underline that draws itself once on load: half a
   second of motion telling you the page is alive, before the widget has
   anything of its own to show. */
.vfmark {
  position: relative; display: inline-flex; align-items: center; gap: .6rem;
  margin: 0 0 2.4rem; font-size: 2.1rem; font-weight: 600; letter-spacing: -.02em;
  background: linear-gradient(180deg, #fff, rgba(255, 255, 255, .75));
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.vfmark img {
  width: 32px; height: 32px; border-radius: 8px; flex-shrink: 0;
  border: 1px solid var(--line);
  box-shadow: 0 6px 20px rgba(0, 0, 0, .35);
}
/* Positioned against the word, not the whole mark: anchoring it to the flex
   row put the far end of the stroke somewhere past the logo entirely. */
.vfmark-word { position: relative; display: inline-block; }
/* The explicit width matters: an absolutely positioned SVG with a height and
   a viewBox resolves its width from the viewBox ratio, not from left/right, so
   left:0;right:0 alone left the stroke running a couple of hundred pixels past
   the end of the word. */
.vfmark-line {
  position: absolute; left: 0; bottom: -.28em;
  width: 100%; height: 10px; overflow: visible;
}
.vfmark-line path {
  fill: none; stroke: var(--accent); stroke-width: 6; stroke-linecap: round;
  stroke-dasharray: 440; stroke-dashoffset: 440;
  animation: vfDraw 1.4s .15s ease forwards;
}
@keyframes vfDraw { to { stroke-dashoffset: 0 } }

/* Both of these start from a hidden state, so without animations the card
   would be blank and the underline missing. Land them on their finished
   frame instead of animating to it. */
@media (prefers-reduced-motion: reduce) {
  .vf-grid { animation: none; opacity: .16; }
  .vfwrap { animation: none; opacity: 1; }
  .vfmark-line path { animation: none; stroke-dashoffset: 0; }
}

.vfcard {
  position: relative;
  padding: 1.5rem; border-radius: 12px;
  background: #0d0c11;
  box-shadow: 0 4px 30px rgba(0, 0, 0, .25);
}
/* Two borders, the second nudged down a pixel. The pair reads as a lit top
   edge and a shadowed bottom one, which is the whole of what gives the card
   its thickness. */
.vfcard::before, .vfcard::after {
  content: ''; position: absolute; inset: 0;
  border-radius: 12px; pointer-events: none;
}
.vfcard::before { border: 1px solid #17161c; }
.vfcard::after { border: 1px solid #221f2a; transform: translateY(1px); }

.vfhead { margin-bottom: 1.5rem; }
.vfhead::after {
  content: ''; display: block; height: 1px; margin-top: 1rem;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .06), transparent);
}
.vftitle {
  display: flex; align-items: center;
  font-size: 1rem; font-weight: 500; margin: 0 0 .5rem;
}
.vftitle::before {
  content: ''; width: 4px; height: 16px; margin-right: 8px; border-radius: 2px;
  background: linear-gradient(180deg, var(--accent), rgba(179, 164, 200, .6));
  box-shadow: 0 0 20px rgba(179, 164, 200, .22);
}
.vfsub { color: var(--muted); font-size: .8rem; margin: 0; }
.vfsub.bad { color: var(--red); }

.vfslot {
  position: relative; min-height: 70px;
  display: flex; align-items: center; justify-content: center;
  margin-bottom: 1.6rem;
}
.vfslot::after {
  content: ''; position: absolute; left: 0; bottom: -10px;
  width: 100%; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .1), transparent);
}

/* The Discord verification page: one spinner, then one glyph. It is the whole
   of the page, so it is sized to be read across a room rather than squinted
   at on a phone held at arm's length. */
.vmspin {
  width: 34px; height: 34px; border-radius: 50%;
  border: 2px solid rgba(255,255,255,.12); border-top-color: var(--accent);
  animation: vmspin 720ms linear infinite;
}
@keyframes vmspin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .vmspin { animation-duration: 2.4s; } }

.vmdone {
  width: 44px; height: 44px; border-radius: 50%;
  display: grid; place-items: center;
  font-size: 1.3rem; font-weight: 700; line-height: 1;
  color: #0b0910; background: var(--accent);
}
.vmdone.bad { background: var(--red); color: #fff; }

.vfray {
  display: flex; justify-content: space-between; gap: 1rem;
  font-size: .7rem; color: var(--dim);
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
}
.vfray span { user-select: text; }

@media (max-width: 480px) {
  .vfmark { font-size: 1.75rem; }
  .vfcard { padding: 1.25rem; }
}

/* ---- dashboard as an application, not a page ---- */

/* The dashboard used to sit inside the marketing page: site nav on top, the
   rail as a rounded card floating in a centred column, everything squeezed
   into the same 1100px the homepage uses. A configuration tool is not a
   document - it wants the whole window, a rail pinned to the edge, and its
   own scroll. This class turns the page into that for the duration. */
body.dashmode { overflow-x: hidden; }
body.dashmode > nav.top,
body.dashmode > footer,
body.dashmode > #toTop { display: none; }
body.dashmode main,
body.dashmode main.wide { max-width: none; margin: 0; padding: 0; }

body.dashmode .dash { display: block; gap: 0; }

/**
 * Three regions, and only the middle one moves.
 *
 * The whole rail used to scroll as one column, so reaching a section near the
 * bottom of a long nav dragged the server switcher off the top of the screen
 * and the language and account rows off the bottom - the two things most
 * likely to be wanted next. Now the rail itself never scrolls, and the nav
 * between the two fixed ends does.
 *
 * `min-height: 0` is the part that is easy to leave out and makes the whole
 * thing fail: a flex child defaults to min-height auto, which refuses to
 * shrink below its content, so the nav grows the rail instead of scrolling
 * inside it and the fixed ends get pushed out of view anyway.
 */
body.dashmode .dash-rail {
  position: fixed; left: 0; top: 0; bottom: 0; width: 264px;
  border-radius: 0; border-width: 0 1px 0 0;
  padding: 1rem .8rem; overflow: hidden;
  display: flex; flex-direction: column;
  background: var(--panel-solid); z-index: 40;
}
body.dashmode .dash-railtop,
body.dashmode .dash-server,
body.dashmode .dash-railfoot { flex: 0 0 auto; }

body.dashmode .dash-nav {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  /* No visible scrollbar. It sat right against the rail's own border and
     read as a second line down the edge of the sidebar rather than as a
     control. Scrolling still works exactly as before - wheel, trackpad,
     touch, keyboard - the bar is only hidden, not disabled. */
  scrollbar-width: none;
  -ms-overflow-style: none;
}
body.dashmode .dash-nav::-webkit-scrollbar { width: 0; height: 0; }

/* The dashboard's own scroll area, same reasoning. */
body.dashmode { scrollbar-width: none; -ms-overflow-style: none; }
body.dashmode::-webkit-scrollbar { width: 0; height: 0; }

body.dashmode .dash-main { margin-left: 264px; padding: 1.7rem 2.2rem 4rem; min-width: 0; }
body.dashmode .dash.collapsed .dash-rail { width: 74px; padding: 1rem .5rem; }
body.dashmode .dash.collapsed .dash-main { margin-left: 74px; }

@media (max-width: 900px) {
  body.dashmode .dash-rail { position: static; width: auto; border-width: 0 0 1px; }
  body.dashmode .dash-main,
  body.dashmode .dash.collapsed .dash-main { margin-left: 0; padding: 1.2rem 1.1rem 3rem; }
  body.dashmode .dash.collapsed .dash-rail { width: auto; }
}

/* The picker and the account row sit in the rail rather than the site nav.
   Both are shared with the docs sidebar; this only fits them here.
   These were still naming .langpick and .langbtn, which belong to the nav
   picker, so they were styling nothing. */
.dash-railfoot .lp-pick { margin-bottom: .1rem; }
.dash.collapsed .dash-railfoot .lp-name,
.dash.collapsed .dash-railfoot .lp-chev,
.dash.collapsed .dash-railfoot .lp-mename { display: none; }
.dash.collapsed .dash-railfoot .lp-btn,
.dash.collapsed .dash-railfoot .lp-mebtn { justify-content: center; }

/* A feature that exists in Discord but has no panel here yet. */
.dash-elsewhere { padding: 1.3rem 1.4rem; }
.dash-elsewhere h3 { margin: 0 0 .4rem; font-size: 1rem; }
.dash-elsewhere code {
  background: var(--panel2); border: 1px solid var(--line);
  border-radius: 5px; padding: .12rem .4rem; color: var(--accent);
}
.dash-cmds { display: flex; flex-wrap: wrap; gap: .4rem; margin-top: .9rem; }


/* ---------- language picker and account row ---------- */

/* Deliberately not `.langbtn` and friends: those belong to the nav picker in
   renderNav, and defining them again down here silently restyled it. */

.lp-pick { position: relative; display: block; }
.lp-btn {
  display: flex; align-items: center; gap: .55rem; width: 100%;
  font: inherit; font-size: .86rem; cursor: pointer; text-align: left;
  color: var(--text); background: var(--panel2, #14121a);
  border: 1px solid var(--line); border-radius: 11px; padding: .5rem .65rem;
  transition: border-color .18s var(--ease), background .18s var(--ease);
}
.lp-btn:hover { background: rgba(255,255,255,.05); border-color: var(--line-hi); }
.lp-pick.open .lp-btn { border-color: var(--line-hi); background: rgba(255,255,255,.05); }
.lp-name { flex: 1; min-width: 0; font-weight: 600; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; }
.lp-chev { width: 15px; height: 15px; flex: 0 0 auto; opacity: .55;
  transition: transform .18s var(--ease); }
.lp-pick.open .lp-chev { transform: rotate(180deg); }

/* The flag is an inline svg from brand.js, sized here rather than there. */
.lp-flag { display: grid; place-items: center; flex: 0 0 auto; }
.lp-flag svg, .lp-flag img {
  width: 20px; height: 14px; border-radius: 3px; display: block;
  box-shadow: 0 0 0 1px rgba(255,255,255,.12) inset;
}
.lp-code {
  display: inline-grid; place-items: center; min-width: 20px; height: 14px;
  border-radius: 3px; background: rgba(255,255,255,.08);
  font-size: .56rem; font-weight: 700; letter-spacing: .04em; color: var(--muted);
}

/* The floating layer both menus move into while open. Fixed, so the rail's
   own overflow cannot clip them. */
.lp-pop { position: fixed; z-index: 300; }

.lp-menu {
  width: max-content; min-width: 15rem; max-width: 20rem;
  display: flex; flex-direction: column; overflow: hidden;
  background: var(--panel2, #14121a); border: 1px solid var(--line-hi, #2a2733);
  border-radius: 14px; box-shadow: 0 20px 50px rgba(0,0,0,.6);
}
/* A display value beats the browser's own [hidden] rule, so without this the
   panel keeps painting while the DOM says it is hidden. */
.lp-menu[hidden] { display: none; }

.lp-find {
  display: flex; align-items: center; gap: .5rem;
  padding: .6rem .75rem; border-bottom: 1px solid var(--line);
}
.lp-find svg { width: 15px; height: 15px; color: var(--dim); flex: 0 0 auto; }
/* The site styles every text input as a rounded pill with its own padding
   and a 220px floor. Inside a menu that is a pill in a box; these are the
   properties that have to be undone rather than just the border. */
.lp-find input[type="text"], .lp-find input[type="text"]:focus {
  flex: 1; min-width: 0; padding: 0; background: none; border: 0;
  border-radius: 0; outline: none; box-shadow: none; color: var(--text);
  font: inherit; font-size: .86rem;
}
.lp-list { max-height: 17rem; overflow-y: auto; padding: .3rem; }
.lp-list::-webkit-scrollbar { width: 8px; }
.lp-list::-webkit-scrollbar-thumb { background: rgba(255,255,255,.09); border-radius: 8px; }

.lp-opt {
  display: flex; align-items: center; gap: .6rem; width: 100%; text-align: left;
  font: inherit; cursor: pointer; color: var(--muted); background: none;
  border: 0; border-radius: 9px; padding: .45rem .55rem;
  transition: background .14s var(--ease), color .14s var(--ease);
}
.lp-opt:hover { background: rgba(255,255,255,.06); color: var(--text); }
.lp-opt.on { background: rgba(255,255,255,.05); color: var(--text); }
.lp-text { display: flex; flex-direction: column; line-height: 1.25; min-width: 0; }
.lp-text b { font-size: .86rem; font-weight: 600; }
.lp-text span { font-size: .72rem; color: var(--dim); }
.lp-opt.on::after {
  content: ""; margin-left: auto; width: 6px; height: 6px;
  border-radius: 50%; background: var(--discord); flex: 0 0 auto;
}
.lp-none { margin: 0; padding: .8rem; color: var(--dim); font-size: .84rem; text-align: center; }

/* ---- the account row ---- */

.lp-me { position: relative; margin-top: .5rem; }
.lp-mebtn {
  display: flex; align-items: center; gap: .55rem; width: 100%;
  font: inherit; font-size: .84rem; cursor: pointer; text-align: left;
  color: var(--muted); background: none;
  border: 1px solid transparent; border-radius: 11px; padding: .4rem .5rem;
  transition: background .18s var(--ease), border-color .18s var(--ease), color .18s var(--ease);
}
.lp-mebtn:hover, .lp-me.open .lp-mebtn {
  background: rgba(255,255,255,.05); border-color: var(--line); color: var(--text);
}
.lp-mebtn img, .lp-fallback {
  width: 26px; height: 26px; border-radius: 50%; flex: 0 0 auto;
  object-fit: cover; background: #1e1f22;
}
.lp-fallback { display: grid; place-items: center; font-size: .74rem;
  font-weight: 600; color: #e6dff2; background: rgba(179,164,200,.2); }

/* Always visible in the rail. It used to slide open on hover, which is fine
   in a nav bar where space is contested but wrong at the foot of a sidebar:
   the row is a fixed anchor people look at to check which account they are
   on, and a name that only appears when you point at it cannot do that.
   The nav bar's own account button keeps its hover reveal - that one really
   is short of room. */
.lp-mename {
  flex: 1; min-width: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* No chevron. The row is obviously a control once it lights up on hover, and
   an arrow on a 26px avatar is more clutter than signpost. */

.lp-memenu {
  display: flex; flex-direction: column; padding: .3rem; min-width: 13rem;
  background: var(--panel2, #14121a); border: 1px solid var(--line-hi, #2a2733);
  border-radius: 14px; box-shadow: 0 20px 50px rgba(0,0,0,.6);
}
.lp-memenu[hidden] { display: none; }
.lp-mewho {
  display: flex; align-items: center; gap: .55rem;
  padding: .55rem .6rem; margin-bottom: .25rem; border-bottom: 1px solid var(--line);
}
.lp-mewho span { display: flex; flex-direction: column; line-height: 1.25; min-width: 0; }
.lp-mewho b { color: var(--text); font-size: .86rem; }
.lp-mewho span span { color: var(--dim); font-size: .74rem; }
.lp-meitem {
  display: block; width: 100%; text-align: left; font: inherit; font-size: .84rem;
  color: var(--muted); background: none; border: 0; border-radius: 9px;
  padding: .45rem .6rem; cursor: pointer; text-decoration: none;
  transition: background .14s var(--ease), color .14s var(--ease);
}
.lp-meitem:hover { background: rgba(255,255,255,.06); color: var(--text); }
.lp-meitem.danger:hover { background: rgba(237,66,69,.14); color: #ff9ea0; }

/* ---------- ban appeal form ---------- */

.apserver {
  display: flex; align-items: center; gap: .8rem; justify-content: center;
  margin: 0 0 1.4rem;
}
.apicon {
  width: 48px; height: 48px; border-radius: 50%; object-fit: cover; background: #1e1f22;
  border: 1px solid rgba(255,255,255,.09); flex: 0 0 auto;
}
.apicon.blank { display: grid; place-items: center; background: rgba(179,164,200,.18); color: #e6dff2; font-weight: 600; }
.apserver strong { color: #fff; font-size: 1.02rem; }

.apform .apfield + .apfield, .apform .apfield + .apcheck { margin-top: 1.15rem; }
.apinput {
  width: 100%; padding: .65rem .8rem; background: #0b0910;
  border: 1px solid var(--line); border-radius: 10px; color: var(--text);
  font: inherit; font-size: .9rem; resize: vertical;
  transition: border-color .2s var(--ease), box-shadow .2s var(--ease);
}
.apinput:focus {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(179,164,200,.12);
}
.apreq {
  font-size: .62rem; text-transform: uppercase; letter-spacing: .07em; font-weight: 600;
  color: var(--dim); background: rgba(255,255,255,.06); border-radius: 4px;
  padding: .1rem .3rem; margin-left: .35rem;
}
.apcheck {
  display: flex; gap: .6rem; align-items: flex-start; margin-top: 1.15rem;
  font-size: .9rem; cursor: pointer;
}
.apcheck input { margin-top: .18rem; flex: 0 0 auto; }

/* Signed in: who you are, and the punishments you can pick from. */
.apme {
  display: flex; align-items: center; gap: .55rem; flex-wrap: wrap;
  padding: .6rem .8rem; background: #0b0910;
  border: 1px solid var(--line); border-radius: 10px;
}
.apme strong { color: #fff; font-size: .92rem; }
.apme code { font-size: .78rem; }

.apcases { display: grid; gap: .5rem; }
.apcase {
  display: flex; gap: .65rem; align-items: flex-start; cursor: pointer;
  padding: .65rem .8rem; background: #0b0910;
  border: 1px solid var(--line); border-radius: 10px;
  transition: border-color .2s var(--ease), background .2s var(--ease);
}
.apcase:hover { border-color: rgba(255,255,255,.16); }
/* No :has fallback needed: without it the radio itself still shows the pick. */
.apcase:has(input:checked) { border-color: var(--accent); background: rgba(179,164,200,.07); }
.apcase input { margin-top: .22rem; flex: 0 0 auto; }
.apcasebody { display: grid; gap: .18rem; min-width: 0; }
.apcasetop { font-size: .86rem; color: #fff; font-weight: 600; }
.apcasewhy {
  font-size: .8rem; color: var(--dim); overflow-wrap: anywhere;
}


/* ---------- checkboxes ---------- */

/* A native checkbox is painted by the operating system: a white box with a
   blue tick, on a black page. `accent-color` only recolours the tick, not the
   box, which is why these still looked like Windows controls after the
   dropdowns were replaced. The whole control is drawn here instead. */
input[type="checkbox"] {
  appearance: none; -webkit-appearance: none;
  width: 17px; height: 17px; flex: 0 0 auto; margin: 0;
  border: 1px solid var(--line-hi, #2a2733); border-radius: 5px;
  background: var(--panel2, #14121a); cursor: pointer; position: relative;
  transition: background .15s var(--ease), border-color .15s var(--ease);
}
input[type="checkbox"]:hover { border-color: var(--line-hi); }
/* The same blue as the toggle switches beside them. A pale fill with a dark
   tick was the whole problem: it read as the operating system's checkbox even
   though it was ours. */
input[type="checkbox"]:checked {
  background: var(--discord); border-color: var(--discord);
}
/* Drawn rather than a glyph: a tick character sits differently in every font,
   and two strokes always land in the same place. */
input[type="checkbox"]:checked::after {
  content: ""; position: absolute; left: 5px; top: 1.5px;
  width: 4px; height: 9px; border: solid #fff;
  border-width: 0 2px 2px 0; transform: rotate(42deg);
}
input[type="checkbox"]:focus-visible {
  outline: none; box-shadow: 0 0 0 3px rgba(179,164,200,.22);
}
input[type="checkbox"]:disabled { opacity: .45; cursor: default; }

/* The toggle switches hide their input behind a drawn track, and this block
   comes after the rule that does it, so it has to be re-asserted. */
.switch input[type="checkbox"] {
  appearance: none; -webkit-appearance: none;
  opacity: 0; width: 0; height: 0; border: 0; background: none;
}
.switch input[type="checkbox"]::after { content: none; }

.modrow input[type="checkbox"] { width: 17px; height: 17px; }

/* Two panes force a smaller box with !important. The tick is nudged to match
   rather than leaving it sitting proud of a 14px square. */
.ebcheck input[type="checkbox"]:checked::after,
.whf-inline input[type="checkbox"]:checked::after { left: 4px; top: 1px; height: 8px; }
.whf-inline input[type="checkbox"]:checked::after { left: 3.5px; height: 7px; }


/* ---------- loading a server ---------- */

/* A bar rather than a spinner in the middle of a blank page. What is already
   on screen stays there and stays readable while the next server is fetched. */
body.dash-busy::before {
  content: ""; position: fixed; left: 0; top: 0; height: 2px; width: 100%;
  z-index: 400; pointer-events: none;
  background: linear-gradient(90deg, transparent, var(--accent), transparent);
  background-size: 40% 100%; background-repeat: no-repeat;
  animation: dashBusy 1.1s linear infinite;
}
@keyframes dashBusy {
  from { background-position: -40% 0; }
  to { background-position: 140% 0; }
}
/* Enough to say "this is not current" without making it unreadable. */
body.dash-busy .dash-main, body.dash-busy #body { opacity: .55; transition: opacity .15s var(--ease); }
body.dash-busy { cursor: progress; }

@media (prefers-reduced-motion: reduce) {
  body.dash-busy::before { animation: none; background-position: 0 0; background-size: 100% 100%; }
}

/* ---- /settings ------------------------------------------------------- */
/* Rows rather than a form: nothing here is saved, each control acts on its
   own the moment it is used, so a Save button would have nothing to do. */
.setrow { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.setwho { display: flex; align-items: center; gap: .7rem; min-width: 0; }
.setwho img, .setfall {
  width: 44px; height: 44px; border-radius: 50%; object-fit: cover; flex: 0 0 auto;
  background: rgba(179,164,200,.2);
}
.setwho strong { display: block; color: #fff; font-size: .95rem; }
.setwho .small { display: block; }
.setlinks { display: flex; flex-wrap: wrap; gap: .5rem; }

/* The discovery card carries a sentence the picker's cards do not, so it gets
   a fixed height: a grid where every card ends at a different point reads as
   broken rather than as varied. */
.dvdesc {
  margin: .5rem 0 .9rem; color: var(--muted); font-size: .82rem; line-height: 1.45;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
  overflow: hidden; min-height: 3.6em;
}

/* ---- Status ------------------------------------------------------------
   A normal page heading. The wordmark version was three times the size of
   every other h1 on the site and pushed the thing people came for below the
   fold, which is a strange trade for a page whose whole job is answering one
   question quickly. */
.sthead {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 1.2rem; flex-wrap: wrap; margin-bottom: 2rem;
}
.sthead h1 { margin: 0; }
.sthead .lede { margin: .3rem 0 0; }
.sthead-up {
  display: inline-flex; align-items: center; gap: .5rem;
  color: var(--muted); font-size: .88rem;
  padding: .4rem .7rem; border: 1px solid var(--line); border-radius: 999px;
  background: var(--panel);
}

/* Titled bands, so the graphs, the service list and the live figures read as
   three separate things rather than one column that happens to change shape
   twice. Each keeps its own vertical space, which is what stopped them
   colliding. */
/* Real air between the bands. They were close enough that the three read as
   one long column rather than as separate answers to separate questions,
   which is the whole reason for splitting them up. */
.stsec { margin-top: 3.2rem; }
.stsec-h {
  margin: 0 0 1.1rem; color: var(--dim);
  font-size: .72rem; font-weight: 600; letter-spacing: .16em; text-transform: uppercase;
}

/* Three across, then two, then one. The graph needs width to say anything,
   so it drops to one column earlier than most grids on the site would. */
.stcards { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1.3rem; }
@media (max-width: 900px) { .stcards { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 620px) { .stcards { grid-template-columns: minmax(0, 1fr); } }

.stcard {
  position: relative; overflow: hidden;
  border: 1px solid var(--line); border-radius: 14px;
  background: var(--panel2); padding: 1.15rem 1.25rem .7rem;
  color: #fff;
}
/* `currentColor` drives the line, the fill gradient and the glow, so a card
   changes colour by changing one property. */
.stcard.hot { color: #ff4d4d; }

.stcard-top { display: flex; align-items: baseline; justify-content: space-between; gap: .8rem; }
.stcard-k {
  color: var(--dim); font-size: .68rem; font-weight: 600;
  letter-spacing: .18em; text-transform: uppercase;
}
.stcard-v { color: #fff; font-size: 1.5rem; font-weight: 700; letter-spacing: -.02em; }

.stcard-graph { margin-top: 1rem; height: 90px; }
.stcard-graph svg { width: 100%; height: 100%; display: block; overflow: visible; }
.stcard-graph .line {
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linejoin: round; stroke-linecap: round;
  filter: drop-shadow(0 0 6px currentColor);
}
.stcard-graph .fill { stroke: none; }
.stcard[data-metric="memory"] .fill { fill: url(#gmemory); }
.stcard[data-metric="cpu"] .fill { fill: url(#gcpu); }
.stcard[data-metric="network"] .fill { fill: url(#gnetwork); }

.stcard-note {
  margin: 0 0 .7rem; color: var(--dim); font-size: .72rem; line-height: 1.4;
}
