/* Shared tokens, reset and chrome.

   Visual language borrows from Wise: an off-white page with SOLID white cards
   sitting on it, very bold headlines on tight leading, full pills, and a single
   saturated accent used as a fill with deep type on top.

   Inherited from BaseAPY (projects/baseline) and re-tinted: greys carry a
   violet cast rather than a green one, and the dark ground is a deep aubergine
   instead of forest, so the accent sits in the same family as the page.

   That is a deliberate shift away from glass-on-white for the light theme —
   translucency needs something behind it to refract, and against a pale page it
   just reads as muddy. Depth here comes from the card being lighter than the
   page plus a soft shadow, which is crisper. The dark theme keeps real glass,
   because against a deep forest ground translucency actually reads.

   Accent vars (--accent fill, --accent-ink on-fill, --accent-text as type) are
   injected by js/brand.js from config.js. Never hardcode them here. */

:root {
  color-scheme: light;

  /* Page is warm grey; cards are white. Not the other way round. */
  --bg: #ECEAEF;
  --bg-2: #F2F0F5;
  --bg-3: #E4E1EA;

  --panel: #FFFFFF;
  --panel-2: #F7F6F9;
  --panel-solid: #FFFFFF;

  --line: rgba(30, 14, 46, 0.10);
  --line-2: rgba(30, 14, 46, 0.20);
  --sheen: transparent;

  /* Greys with a violet cast — neutral greys read as dirty next to the
     accent. */
  --ink: #16101E;
  --ink-2: #4A4453;
  --ink-3: #6E6878;

  --shadow-sm: 0 1px 2px rgba(30, 14, 46, 0.05), 0 3px 10px -6px rgba(30, 14, 46, 0.12);
  --shadow: 0 2px 4px rgba(30, 14, 46, 0.04), 0 14px 34px -18px rgba(30, 14, 46, 0.18);
  --shadow-lg: 0 4px 10px rgba(30, 14, 46, 0.05), 0 36px 72px -38px rgba(30, 14, 46, 0.26);

  --glow: transparent;

  --r-sm: 10px;
  --r: 16px;
  --r-lg: 24px;
  --r-xl: 32px;

  --sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
  --serif: 'Instrument Serif', 'Iowan Old Style', Georgia, serif;
  --mono: ui-monospace, 'SF Mono', SFMono-Regular, Menlo, monospace;

  --maxw: 1240px;
  --blur: 22px;
}

:root[data-theme='dark'] {
  color-scheme: dark;

  /* Deep aubergine rather than neutral black, so the violet sits in the same
     family as its ground. */
  --bg: #0B0710;
  --bg-2: #110B18;
  --bg-3: #180F22;

  --panel: rgba(255, 255, 255, 0.05);
  --panel-2: rgba(255, 255, 255, 0.085);
  --panel-solid: #180F22;

  --line: rgba(255, 255, 255, 0.10);
  --line-2: rgba(255, 255, 255, 0.18);
  --sheen: rgba(255, 255, 255, 0.13);

  --ink: #F2EFF6;
  --ink-2: #ADA4B8;
  --ink-3: #736A80;

  --shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.4);
  --shadow: 0 18px 44px -24px rgba(0, 0, 0, 0.8);
  --shadow-lg: 0 44px 96px -48px rgba(0, 0, 0, 0.95);

  --glow: var(--accent-line);
}

* { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  /* Sticky nav must not cover the target of an in-page anchor. */
  scroll-padding-top: 84px;
}

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

body { min-height: 100vh; overflow-x: hidden; }

/* Light mode is a flat ground — no gradient wash, which is what keeps the
   white cards looking crisp. Dark mode keeps the two soft light sources so its
   glass has something to refract. */
:root[data-theme='dark'] body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  background:
    radial-gradient(940px 560px at 16% -10%, var(--accent-soft), transparent 62%),
    radial-gradient(820px 520px at 88% 2%, rgba(168, 85, 247, 0.07), transparent 60%),
    linear-gradient(180deg, var(--bg-2), var(--bg) 44%);
  pointer-events: none;
}

a { color: inherit; text-decoration: none; }

/* Wise's headline signature: near-black weight on leading tighter than the
   font size. Anything lighter than 800 loses the effect entirely. */
h1, h2, h3 {
  margin: 0;
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1.05;
}

/* Prices must not jitter as digits change. */
.num, td.num, .price { font-variant-numeric: tabular-nums; font-feature-settings: 'tnum' 1; }

.wrap { width: 100%; max-width: var(--maxw); margin: 0 auto; padding: 0 24px; }

/* --- surfaces ------------------------------------------------------------- */

.glass {
  position: relative;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow), inset 0 1px 0 var(--sheen);
}

:root[data-theme='dark'] .glass {
  backdrop-filter: blur(var(--blur)) saturate(180%);
  -webkit-backdrop-filter: blur(var(--blur)) saturate(180%);
}

/* --- live background ------------------------------------------------------ */

/* The flow-field canvas (js/bg.js). Fixed, behind all content, and inert to
   the pointer — it reacts to the cursor by listening on window, never by
   receiving events, so it cannot swallow a click on anything above it. */
.bg-flow {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  display: block;
}

/* The dark theme's gradient wash drops one layer so the canvas paints over it. */
:root[data-theme='dark'] body::before { z-index: -2; }

/* --- scroll reveal -------------------------------------------------------- */

/* Applied by js/reveal.js. The un-revealed state is only set when JS is running
   (html.js-reveal), so with JS off or broken everything stays visible instead of
   leaving a blank page. */
.js-reveal [data-reveal] {
  opacity: 0;
  transform: translateY(22px);
  will-change: opacity, transform;
}

.js-reveal [data-reveal].in {
  opacity: 1;
  transform: none;
  transition:
    opacity 0.72s cubic-bezier(0.22, 0.61, 0.36, 1),
    transform 0.72s cubic-bezier(0.22, 0.61, 0.36, 1);
  transition-delay: var(--reveal-delay, 0ms);
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .js-reveal [data-reveal] { opacity: 1; transform: none; }
  .js-reveal [data-reveal].in { transition: none; }
}

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

.nav {
  position: sticky;
  top: 0;
  z-index: 60;
  height: 66px;
  display: flex;
  align-items: center;
  border-bottom: 1px solid transparent;
  transition: border-color 0.25s, background 0.25s;
}

/* Chrome only appears once the page has moved. */
.nav.stuck {
  border-bottom-color: var(--line);
  background: var(--bg);
}

:root[data-theme='dark'] .nav.stuck {
  background: rgba(11, 7, 16, 0.74);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
}

.nav .wrap { display: flex; align-items: center; gap: 26px; }

.brand {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 17px;
  font-weight: 800;
  letter-spacing: -0.035em;
}

/* The real logo (assets/logo.svg). Its rounding is baked into the artwork as
   rx="24" on the plate; the border-radius here is a safety net for the same
   reason PerpsHub keeps one — if the mark is ever swapped for a square raster,
   the corners still read as rounded. */
.brand-mark {
  width: 23px;
  height: 23px;
  border-radius: 6.5px;
  flex: none;
  display: block;
}

.nav-links { display: flex; gap: 20px; font-size: 14px; font-weight: 500; color: var(--ink-2); }
.nav-links a { transition: color 0.15s; }
.nav-links a:hover, .nav-links a.on { color: var(--ink); }

.nav-right { margin-left: auto; display: flex; align-items: center; gap: 10px; }

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

/* Full pills. Wise uses 9999px on essentially every interactive element. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  height: 40px;
  padding: 0 18px;
  border: 1px solid var(--line-2);
  border-radius: 999px;
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.16s, border-color 0.16s, transform 0.16s, box-shadow 0.16s;
}

.btn:hover { background: var(--panel-2); border-color: var(--line-2); }
.btn:active { transform: translateY(1px); }

:root[data-theme='dark'] .btn { background: var(--panel); }
:root[data-theme='dark'] .btn:hover { background: var(--panel-2); }

/* Violet fill, near-black violet type. The fill is mid-tone, so on-fill type
   is the dark ink rather than white. */
.btn-accent {
  background: var(--accent);
  border-color: transparent;
  color: var(--accent-ink);
  font-weight: 700;
}

.btn-accent:hover { background: var(--accent); filter: brightness(1.04); color: var(--accent-ink); }

.btn-icon { width: 40px; padding: 0; flex: none; }

/* --- pills / badges ------------------------------------------------------ */

.pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 26px;
  padding: 0 11px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--panel);
  font-size: 12px;
  font-weight: 500;
  color: var(--ink-2);
  white-space: nowrap;
}

.pill .dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; }

.pill-live { color: var(--accent-text); border-color: var(--accent-line); background: var(--accent-soft); }
.pill-live .dot { animation: pulse 2.1s ease-in-out infinite; }
.pill-stale { color: #8A5A00; border-color: rgba(138, 90, 0, 0.3); }
.pill-down { color: var(--bad); border-color: rgba(194, 51, 74, 0.32); }

:root[data-theme='dark'] .pill-stale { color: #F0B429; }

@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }

/* --- misc ---------------------------------------------------------------- */

.eyebrow {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.muted { color: var(--ink-2); }
.dim { color: var(--ink-3); }
.good { color: var(--accent-text); }
.bad { color: var(--bad); }

.footer {
  margin-top: 96px;
  border-top: 1px solid var(--line);
  padding: 32px 0 48px;
  font-size: 13px;
  color: var(--ink-3);
}

.footer .wrap { display: flex; flex-wrap: wrap; gap: 16px; align-items: center; }
.footer a:hover { color: var(--ink-2); }

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

/* 900px, not the chassis default of 720px. LastCommit's nav carries five labels
   ("The split / All tokens / Still shipping / No public code / Method") which
   measure 413px — wider than RealFloat's set. Between 720 and 900 the links fit
   only by crushing the brand, which truncated to "LastCo…". Raising the
   breakpoint hands those widths to the hamburger instead.
   MUST match the same media query in css/base.css, which hides .nav-links; the
   two disagreeing leaves a band with no navigation at all. */
@media (max-width: 900px) {
  .wrap { padding: 0 16px; }
  .nav-links { display: none; }
}

/* Social link in the footer. Sits on the baseline with the other footer items,
   so the glyph is nudged rather than letting flex stretch it. */
.footer .social {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-weight: 600;
  color: var(--ink-2);
  transition: color 0.15s;
}

.footer .social:hover { color: var(--ink); }
.footer .social svg { flex: none; }
