/* Shared design system for every Aero route.
   CSP is strict (style-src 'self', script-src 'self'), so nothing here is
   generated by an inline style attribute and no rule depends on JS.

   Visual language: pure-black canvas, one light source from the top-right, and
   controls that read as machined parts (solid #131313 fill, hairline border,
   inset highlight on the top edge and inset shade underneath). Type is Archivo
   at 500 rather than 700 so headlines stay calm at large sizes. */

@font-face {
  font-family: Archivo;
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/fonts/archivo-var-latin.woff2") format("woff2");
}

:root {
  --bg: #000;
  --fg: #fff;
  --muted: rgba(255, 255, 255, .62);
  --faint: rgba(255, 255, 255, .4);
  --line: rgba(255, 255, 255, .09);
  --line-strong: rgba(255, 255, 255, .18);
  --card: #0b0b0b;
  --card-hover: #101010;
  --up: #22e584;
  --down: #f05252;
  --warn: #f5b94a;
  --nodata: rgba(255, 255, 255, .13);
  /* Matches embedColor in the bot's config.json so the site and the Discord
     embeds read as one product. */
  --accent: #00bfff;
  /* The machined part: fill, seam, and the two inset edges that make it look
     raised rather than printed. */
  --metal: #131313;
  --metal-line: #202020;
  --metal-hi: #242424;
  --metal-lo: #0e0e0e;
  --metal-hi-hover: #2e2e2e;
  --bevel: inset 0 1px 0 0 var(--metal-hi), inset 0 -1px 0 0 var(--metal-lo);
  --ease: cubic-bezier(.22, 1, .36, 1);
  --display: "Archivo", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --body: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --shell: 1080px;
  --gutter: clamp(1.1rem, 4vw, 2.5rem);
  --radius: 14px;
}

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

/* Text stays selectable on content pages: install steps and key formats have to
   be copyable. The bot's own key display keeps its own guard. */
html { background: var(--bg); -webkit-text-size-adjust: 100%; text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--body);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  position: relative;
  isolation: isolate;
}

/* One light source: rays fanned out of the top-right corner, blurred and added
   to the black with screen blending so only the highlights survive. */
.beam {
  position: fixed; top: 0; right: 0; z-index: -1; pointer-events: none;
  width: min(52vw, 640px); height: min(74vh, 700px);
  mix-blend-mode: screen; filter: blur(7px); opacity: .78;
  background:
    radial-gradient(120% 120% at 100% 0, rgba(255, 255, 255, .1) 0, rgba(255, 255, 255, .03) 24%, transparent 56%),
    conic-gradient(from 0deg at 100% 0,
      transparent 188deg,
      rgba(255, 255, 255, .09) 196deg, transparent 202deg,
      rgba(0, 191, 255, .07) 209deg, transparent 214deg,
      rgba(255, 255, 255, .11) 221deg, transparent 227deg,
      rgba(255, 255, 255, .05) 233deg, transparent 239deg,
      rgba(255, 255, 255, .08) 245deg, transparent 251deg,
      rgba(0, 191, 255, .05) 257deg, transparent 264deg,
      transparent 360deg);
  -webkit-mask: radial-gradient(140% 140% at 100% 0, #000 0, #000 30%, transparent 74%);
  mask: radial-gradient(140% 140% at 100% 0, #000 0, #000 30%, transparent 74%);
}

/* Understated floor gradient so long content pages do not read as flat void. */
.bg { position: fixed; inset: 0; z-index: -2; pointer-events: none; background: radial-gradient(ellipse 70% 46% at 50% 116%, rgba(255, 255, 255, .045), transparent 70%); }

::selection { background: rgba(0, 191, 255, .28); color: #fff; }

a { color: inherit; }

h1, h2, h3 { font-family: var(--display); font-weight: 500; letter-spacing: -.035em; line-height: 1.06; margin: 0; text-wrap: balance; }
h1 { font-size: clamp(2.15rem, 5vw, 3.4rem); }
h2 { font-size: clamp(1.42rem, 2.9vw, 1.95rem); letter-spacing: -.03em; }
h3 { font-size: 1.06rem; font-weight: 600; letter-spacing: -.018em; line-height: 1.25; }
p { margin: 0; }
code, kbd, samp { font-family: var(--mono); font-size: .88em; }

code:not(pre code) {
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: .1em .4em;
  background: rgba(255, 255, 255, .06);
  /* nowrap here pushed long tokens (client-version URLs, key shapes) past the
     390px viewport; breaking is uglier than scrolling. */
  white-space: normal;
  overflow-wrap: anywhere;
}

.shell { width: 100%; max-width: var(--shell); margin-inline: auto; padding-inline: var(--gutter); }

.skip-link {
  position: absolute; left: .5rem; top: -3rem; z-index: 20;
  background: #fff; color: #000; padding: .55rem .9rem; border-radius: 8px;
  font-weight: 600; text-decoration: none; transition: top .15s ease;
}
.skip-link:focus { top: .5rem; }

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

/* ---------------------------------------------------------------- navigation
   Floating chips instead of a bar: the brand, a centered segmented control and
   the action pills each sit on the black with nothing behind them, so content
   scrolls past through the gaps. */
.nav { position: sticky; top: 0; z-index: 12; padding-block: .8rem; }
.nav-in {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 1rem;
  min-height: 44px;
}
.brand {
  justify-self: start; display: inline-flex; align-items: center; gap: .5rem;
  padding: .34rem .8rem .34rem .45rem; text-decoration: none;
  font-family: var(--display); font-weight: 700; font-size: 1rem; letter-spacing: -.03em;
  border-radius: 999px;
}
.brand img { display: block; width: 24px; height: auto; }

/* The segmented control. Cells are equal width, so the indicator can be one
   sixth of the track and move in whole steps — no JS to measure anything. */
.tabs {
  position: relative; display: flex; gap: 2px; padding: 3px;
  border: 1px solid var(--metal-line); border-radius: 999px;
  background: rgba(11, 11, 11, .82);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  box-shadow: var(--bevel);
}
.tab {
  position: relative; z-index: 1; flex: 1 1 0; min-width: 0; text-align: center;
  padding: .42rem .78rem; border-radius: 999px; text-decoration: none;
  font-family: var(--display); font-weight: 500; font-size: .82rem; letter-spacing: -.012em;
  color: #6e6e6e; transition: color .2s var(--ease);
  white-space: nowrap;
}
.tab:hover { color: rgba(255, 255, 255, .82); }
.tab.is-on { color: rgba(255, 255, 255, .95); }
.tab-ind {
  position: absolute; top: 3px; bottom: 3px; left: 3px; z-index: 0;
  width: calc((100% - 6px - 10px) / 6);
  border-radius: 999px; background: var(--metal);
  border: 1px solid var(--metal-line); box-shadow: var(--bevel);
  transition: transform .3s var(--ease);
}
/* 6 cells + the indicator itself as the first child. */
.tabs:has(.tab:nth-child(2).is-on) .tab-ind { transform: translateX(0); }
.tabs:has(.tab:nth-child(3).is-on) .tab-ind { transform: translateX(calc(100% + 2px)); }
.tabs:has(.tab:nth-child(4).is-on) .tab-ind { transform: translateX(calc(200% + 4px)); }
.tabs:has(.tab:nth-child(5).is-on) .tab-ind { transform: translateX(calc(300% + 6px)); }
.tabs:has(.tab:nth-child(6).is-on) .tab-ind { transform: translateX(calc(400% + 8px)); }
.tabs:has(.tab:nth-child(7).is-on) .tab-ind { transform: translateX(calc(500% + 10px)); }
/* /get-key and /admin are actions, not tabs: with no active cell the indicator
   would otherwise sit on "Home" and claim it was current. */
.tabs:not(:has(.tab.is-on)) .tab-ind { opacity: 0; }

.nav-act { justify-self: end; display: flex; align-items: center; gap: .5rem; }
.nav-cta { font-size: .84rem !important; padding: .45rem .95rem !important; }
.icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: 999px;
  background: var(--metal); border: 1px solid var(--metal-line); box-shadow: var(--bevel);
  transition: background .2s var(--ease), border-color .2s var(--ease), transform .2s var(--ease);
}
.icon-btn svg { width: 16px; height: 16px; fill: #fff; }
@media (hover: hover) and (pointer: fine) {
  .icon-btn:hover { background: #181818; border-color: #2a2a2a; transform: translateY(-1px); }
}
.icon-btn:active { transform: scale(.95); }

/* Mobile disclosure. <details> is the button: no JS, keyboard and screen-reader
   semantics come for free. */
.menu { display: none; justify-self: end; }
.menu > summary {
  list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: .45rem;
  padding: .45rem .9rem; border-radius: 999px;
  background: var(--metal); border: 1px solid var(--metal-line); box-shadow: var(--bevel);
  font-family: var(--display); font-weight: 500; font-size: .84rem; color: #fff;
  touch-action: manipulation;
}
.menu > summary::-webkit-details-marker { display: none; }
.menu[open] > summary { background: #181818; }
.menu-body {
  position: absolute; right: var(--gutter); left: var(--gutter); top: 56px; z-index: 13;
  display: grid; gap: .1rem; padding: .5rem;
  border: 1px solid var(--metal-line); border-radius: var(--radius);
  background: rgba(11, 11, 11, .97);
  box-shadow: var(--bevel), 0 18px 40px rgba(0, 0, 0, .7);
}
.menu-body a { display: block; padding: .7rem .8rem; border-radius: 9px; color: var(--muted); text-decoration: none; font-size: .95rem; }
.menu-body a.is-on, .menu-body a[aria-current="page"] { color: #fff; background: var(--card-hover); }
.menu-body a:active { background: var(--card-hover); }

@media (max-width: 1000px) {
  .tabs, .nav-act { display: none; }
  .nav-in { grid-template-columns: 1fr auto; }
  .menu { display: block; }
}

/* ---------------------------------------------------------------- pills */
.pill {
  display: inline-flex; align-items: center; gap: .5rem;
  padding: .44rem .85rem; border-radius: 999px;
  background: var(--metal); border: 1px solid var(--metal-line); box-shadow: var(--bevel);
  color: var(--muted); font-family: var(--display); font-weight: 500;
  font-size: .78rem; letter-spacing: -.01em; text-decoration: none; white-space: nowrap;
  touch-action: manipulation;
  transition: color .2s var(--ease), background .2s var(--ease), border-color .2s var(--ease), transform .2s var(--ease);
}
@media (hover: hover) and (pointer: fine) { .pill:hover { color: #fff; background: #181818; border-color: #2a2a2a; } }
.pill:active { transform: scale(.97); color: #fff; }
.pill svg { width: 15px; height: 15px; opacity: .72; flex: none; }
.pill strong { color: #fff; font-weight: 600; font-variant-numeric: tabular-nums; }

.sdot { width: 8px; height: 8px; border-radius: 50%; background: #71717a; flex: none; }
.sdot.up { background: var(--up); animation: pulse-up 2.2s ease-out infinite; }
.sdot.down { background: var(--down); animation: pulse-down 2.2s ease-out infinite; }
@keyframes pulse-up {
  0% { box-shadow: 0 0 0 0 rgba(34, 229, 132, .45); }
  70% { box-shadow: 0 0 0 9px rgba(34, 229, 132, 0); }
  100% { box-shadow: 0 0 0 0 rgba(34, 229, 132, 0); }
}
@keyframes pulse-down {
  0% { box-shadow: 0 0 0 0 rgba(240, 82, 82, .45); }
  70% { box-shadow: 0 0 0 9px rgba(240, 82, 82, 0); }
  100% { box-shadow: 0 0 0 0 rgba(240, 82, 82, 0); }
}

/* Buttons are the same machined part as the pills, one size up. The primary is
   the inverted bevel, so the two belong to one family on a black canvas. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  padding: .7rem 1.3rem; border-radius: 999px;
  border: 1px solid var(--metal-line); background: var(--metal); box-shadow: var(--bevel);
  font-family: var(--display); font-weight: 500; font-size: .95rem; letter-spacing: -.014em;
  color: rgba(255, 255, 255, .82); text-decoration: none; cursor: pointer;
  touch-action: manipulation;
  transition: background .2s var(--ease), border-color .2s var(--ease), color .2s var(--ease), transform .2s var(--ease), box-shadow .2s var(--ease);
}
.btn-primary {
  background: linear-gradient(180deg, #fff, #dedede); color: #0a0a0a; border-color: #f2f2f2;
  box-shadow: inset 0 1px 0 0 #fff, inset 0 -1px 0 0 rgba(0, 0, 0, .22);
  font-weight: 600;
}
@media (hover: hover) and (pointer: fine) {
  .btn:hover { background: #181818; border-color: #2a2a2a; color: #fff; transform: translateY(-1px); box-shadow: inset 0 1px 0 0 var(--metal-hi-hover), inset 0 -1px 0 0 var(--metal-lo); }
  .btn-primary:hover { background: linear-gradient(180deg, #fff, #cfcfcf); color: #000; box-shadow: inset 0 1px 0 0 #fff, inset 0 -1px 0 0 rgba(0, 0, 0, .22); }
}
.btn:active { transform: scale(.97); }

/* ----------------------------------------------------------------- sections */
.eyebrow {
  display: flex; align-items: center; gap: .7rem;
  font-family: var(--mono); font-size: .7rem; letter-spacing: .18em; text-transform: uppercase;
  color: var(--faint); margin-bottom: .8rem;
}
.eyebrow::after { content: ""; height: 1px; flex: 1; background: var(--line); max-width: 120px; }
.hero .eyebrow { justify-content: center; }
.hero .eyebrow::before { content: ""; height: 1px; flex: 1; background: var(--line); max-width: 120px; }
.hero .eyebrow::after { max-width: 120px; }

section { padding-block: clamp(3rem, 8vw, 5.5rem); border-top: 1px solid var(--line); }
section:first-of-type { border-top: 0; }
.lede { max-width: 62ch; color: var(--muted); font-size: 1.02rem; }
.lede strong { color: #fff; font-weight: 600; }

/* ------------------------------------------------------------------- tables */
.spec { width: 100%; table-layout: fixed; border-collapse: collapse; font-size: .92rem; }
.spec th, .spec td { overflow-wrap: anywhere; text-align: left; padding: .8rem .6rem; border-bottom: 1px solid var(--line); vertical-align: top; }
.spec th { color: var(--faint); font-weight: 500; font-family: var(--mono); font-size: .72rem; letter-spacing: .1em; text-transform: uppercase; width: 40%; }
.spec tr:last-child th, .spec tr:last-child td { border-bottom: 0; }
.spec td { color: #fff; }
.spec .pending { color: var(--faint); font-style: italic; }

/* ------------------------------------------------------------------ callout */
.callout {
  display: grid; gap: .35rem; padding: 1rem 1.15rem;
  border: 1px solid var(--metal-line); border-left: 2px solid var(--accent);
  border-radius: 12px; background: var(--card); font-size: .92rem; color: var(--muted);
}
.callout strong { color: #fff; }
.callout-warn { border-left-color: var(--warn); }

/* ------------------------------------------------------------------- footer */
footer.foot { margin-top: auto; border-top: 1px solid var(--line); padding-block: 2.6rem 3rem; color: var(--faint); font-size: .8rem; }
.foot-in { display: grid; gap: 1.6rem; }
.foot-cols { display: grid; gap: 1.6rem; grid-template-columns: repeat(auto-fit, minmax(min(160px, 100%), 1fr)); }
.foot h4 { margin: 0 0 .55rem; font-family: var(--mono); font-size: .68rem; letter-spacing: .16em; text-transform: uppercase; color: var(--faint); font-weight: 500; }
.foot ul { list-style: none; margin: 0; padding: 0; display: grid; gap: .4rem; }
.foot a { color: var(--muted); text-decoration: none; transition: color .2s var(--ease); }
@media (hover: hover) and (pointer: fine) { .foot a:hover { color: #fff; } }
.legal { display: grid; gap: .35rem; padding-top: 1.2rem; border-top: 1px solid var(--line); }
.legal p { max-width: 70ch; }

/* ------------------------------------------------------- entrance motion
   Blur-out reveals, staggered by position. Deliberately nth-child rather than
   per-element animation-delay: an inline style attribute would need a CSP
   exception, and none of this runs without JS either way. */
@keyframes rise-in { from { opacity: 0; filter: blur(10px); transform: translateY(14px); } to { opacity: 1; filter: blur(0); transform: none; } }
@keyframes word-in { from { opacity: 0; filter: blur(9px); transform: translateY(16px); } to { opacity: 1; filter: blur(0); transform: none; } }

/* Astro emits no whitespace between the spans, so the gap is a margin. Both of
   these sit OUTSIDE the motion query: inline-block and spacing are layout, and
   a reader with reduce set must still get readable words. */
.w { display: inline-block; }
.w + .w { margin-left: .26em; }

@media (prefers-reduced-motion: no-preference) {
  /* Only a `from` keyframe: the end value comes from .beam's own opacity, so the
     animation cannot override it once it settles. */
  .beam { animation: beam-in 1.2s var(--ease) both; }
  @keyframes beam-in { from { opacity: 0; } }

  .rise > * { opacity: 0; animation: rise-in .7s var(--ease) forwards; }
  .rise > :nth-child(1) { animation-delay: .04s; }
  .rise > :nth-child(2) { animation-delay: .1s; }
  .rise > :nth-child(3) { animation-delay: .16s; }
  .rise > :nth-child(4) { animation-delay: .22s; }
  .rise > :nth-child(5) { animation-delay: .28s; }
  .rise > :nth-child(6) { animation-delay: .34s; }
  .rise > :nth-child(7) { animation-delay: .4s; }

  .w { opacity: 0; animation: word-in .5s var(--ease) forwards; }
  .w:nth-of-type(1) { animation-delay: .06s; }
  .w:nth-of-type(2) { animation-delay: .11s; }
  .w:nth-of-type(3) { animation-delay: .16s; }
  .w:nth-of-type(4) { animation-delay: .21s; }
  .w:nth-of-type(5) { animation-delay: .26s; }
  .w:nth-of-type(6) { animation-delay: .31s; }
  .w:nth-of-type(7) { animation-delay: .36s; }
  .w:nth-of-type(8) { animation-delay: .41s; }
}

/* ------------------------------------------------------- scroll reveal (JS-free) */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .reveal { animation: reveal-in linear both; animation-timeline: view(); animation-range: entry 0% entry 42%; }
    @keyframes reveal-in { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: none; } }
  }
}

/* ------------------------------------------------------- devtools block layer */
.dt-block {
  position: fixed; inset: 0; z-index: 2147483647;
  display: grid; place-items: center; padding: 1.5rem;
  background: var(--bg); color: #fff; font-family: var(--body); text-align: center;
}

/* landing.js toggles these attributes, and the toast is its only status channel. */
[hidden] { display: none !important; }
.plain { text-decoration: none; }
.gap-top { margin-top: 1.8rem; }
.gap-top-s { margin-top: 1.3rem; }

/* Page chrome: every route except the landing has this heading block, so it
   lives with the shared tokens rather than in the content stylesheet. */
.doc-head { padding-block: clamp(2.6rem, 6vw, 4.4rem) clamp(1.4rem, 3vw, 2rem); }
.doc-head h1 { font-size: clamp(2rem, 4.6vw, 3rem); }
.doc-head .lede { margin-top: 1rem; }
.crumbs { font-family: var(--mono); font-size: .7rem; letter-spacing: .12em; text-transform: uppercase; color: var(--faint); margin-bottom: 1rem; }
.crumbs a { color: var(--faint); text-decoration: none; }
@media (hover: hover) and (pointer: fine) { .crumbs a:hover { color: #fff; } }

.toast {
  position: fixed;
  left: 50%;
  bottom: calc(1.4rem + env(safe-area-inset-bottom, 0px));
  transform: translateX(-50%);
  z-index: 20;
  max-width: min(90vw, 420px);
  border: 1px solid var(--metal-line);
  border-radius: 999px;
  background: rgba(19, 19, 19, .94);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  box-shadow: var(--bevel), 0 14px 40px rgba(0, 0, 0, .6);
  color: var(--muted);
  font-size: .85rem;
  line-height: 1.5;
  padding: .65rem 1.15rem;
  text-align: center;
  pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
  .toast { animation: toast-in .25s var(--ease) both; }
  @keyframes toast-in {
    from { opacity: 0; transform: translate(-50%, 8px); filter: blur(6px); }
    to { opacity: 1; transform: translate(-50%, 0); filter: blur(0); }
  }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .sdot.up, .sdot.down { animation: none; }
  .pill, .btn, .icon-btn, .tab-ind { transition: none; }
  .btn:hover, .icon-btn:hover { transform: none; }
  .pill:active, .btn:active, .icon-btn:active { transform: none; }
}
