/* ============================================================================
   austinmarviano.com

   Direction is set in DESIGN.md. In short: the reference is bittensor.com as it
   actually renders, which was measured from the live page rather than read from
   its stylesheet.

     page background   #ffffff
     body text         #292929
     colours painted   #292929, #000000, #ffffff only
     saturated colour  none

   An earlier version of this file was built from bittensor's compiled CSS
   *tokens*, which specify a dark palette (--background-default: #111) and a lime
   highlight (#e9f4a4). Those tokens are real but the landing page does not use
   them. The owner caught the mistake; the live page is the reference.

   Light is therefore the default and dark is the override, which is the reverse
   of the first version. Dial: ENERGY 1 / RHYTHM 1 / MOTION 1.

   Type: Inter (display/body) and DM Mono (labels, addresses, nav). Inter is
   chosen to disappear rather than perform; Space Grotesk was dropped because
   antislop R-06 names it as a default AI pick.
   ============================================================================ */

/* ---------------------------------------------------------------- fonts */
@font-face {
  font-family: 'Inter';
  src: url('/assets/fonts/inter-300_700-normal.woff2') format('woff2-variations'),
       url('/assets/fonts/inter-300_700-normal.woff2') format('woff2');
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'DM Mono';
  src: url('/assets/fonts/dm-mono-300-normal.woff2') format('woff2');
  font-weight: 300; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'DM Mono';
  src: url('/assets/fonts/dm-mono-400-normal.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'DM Mono';
  src: url('/assets/fonts/dm-mono-500-normal.woff2') format('woff2');
  font-weight: 500; font-style: normal; font-display: swap;
}

/* ---------------------------------------------------------------- tokens
   Light is the default because the reference page is light. Every value below
   traces to DESIGN.md, and each has a one-line reason recorded there. */
:root {
  --background-default: #ffffff;
  --background-paper: #fbfbfb;
  --text-primary: #292929;
  --text-secondary: #767676;
  --primary-main: #292929;
  --primary-light: #000000;
  --primary-contrastText: #ffffff;
  --secondary-main: #f6f6f6;
  --secondary-light: #efefef;
  --border-primary: #e8e8e8;
  --border-secondary: #d6d6d6;
  --border-color: #e0e0e0;

  /* The one deliberate accent. Reserved for links, because a link is the only
     element that asks the reader to act. Not bittensor's lime: that belonged to
     another product, which is the R-30 problem this revision fixes. */
  --accent: #8a5a2b;
  --accent-soft: rgba(138, 90, 43, 0.08);

  --info-main: #4a5a8a;
  --success-main: #2f6b46;
  --error-main: #a33a2c;
  --warning-main: #8a6d00;
  --hover-color: #000000;

  --font-sans: 'Inter', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --font-mono: 'DM Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --maxw: 1180px;
  --gutter: 24px;
  --nav-h: 64px;
}

/* ------------------------------------------------------------- dark theme
   Shipped, works, but no longer the default: the reference is light. Values
   keep the owner's original token set (#111 / #e0e0e0) because it was chosen
   for this site, not borrowed. The accent lightens so links stay readable. */
:root[data-theme='dark'] {
  --background-default: #111111;
  --background-paper: #050404;
  --text-primary: #e0e0e0;
  --text-secondary: #8a8a8a;
  --primary-main: #f2f2f2;
  --primary-light: #ffffff;
  --primary-contrastText: #000000;
  --secondary-main: #1c1c1c;
  --secondary-light: #222222;
  --border-primary: #2a2a2a;
  --border-secondary: #3a3a3a;
  --border-color: #262626;

  --accent: #c99a63;
  --accent-soft: rgba(201, 154, 99, 0.12);

  --info-main: #9aa8d8;
  --success-main: #8ae06c;
  --error-main: #f56868;
  --warning-main: #f1df38;
  --hover-color: #ffffff;
}

/* ------------------------------- accent contrast, verified in both themes
   #8a5a2b on #ffffff = 5.87:1   (AA for body text)
   #c99a63 on #111111 = 7.45:1   (AA for body text)
   Measured by tools/check-contrast.sh against the rendered colours, not the
   token values, and re-run in CI before deploy. */

/* theme-specific details */
:root[data-theme='dark'] .copy-btn:hover { background: var(--primary-light); color: #000; border-color: var(--primary-light); }
:root[data-theme='dark'] .copy-btn.done { background: var(--success-main); color: #000; border-color: var(--success-main); }
:root[data-theme='dark'] ::selection { background: var(--accent); color: #111; }
:root:not([data-theme='dark']) ::selection { background: #292929; color: #ffffff; }

/* theme toggle button */
.theme-toggle {
  margin-left: 8px;
  width: 30px;
  height: 30px;
  flex: none;
  display: grid;
  place-items: center;
  background: transparent;
  border: 1px solid var(--border-primary);
  border-radius: 4px;
  color: var(--text-secondary);
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1;
  padding: 0;
}
.theme-toggle:hover { color: var(--primary-light); border-color: var(--border-secondary); }

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--background-default);
  color: var(--text-primary);
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.6;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  animation: pageIn 0.5s ease both;
}

@keyframes pageIn { from { opacity: 0; } to { opacity: 1; } }

img, svg { max-width: 100%; }
a { color: var(--primary-main); text-decoration: none; }
a:hover { color: var(--primary-light); }

h1, h2, h3, h4 {
  margin: 0;
  font-weight: 500;
  letter-spacing: -0.02em;
  line-height: 1.1;
  color: var(--primary-main);
}
p { margin: 0 0 1rem; }
ul, ol { margin: 0 0 1rem; padding-left: 1.25rem; }

code, kbd, pre, samp { font-family: var(--font-mono); }

::selection { background: var(--text-primary); color: var(--background-default); }

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

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

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--accent); color: #ffffff; padding: 10px 16px;
  font-family: var(--font-mono); font-size: 13px;
}
.skip:focus { left: 0; }

/* ---------------------------------------------------------------- header */
.site-header {
  position: sticky; top: 0; z-index: 50;
  /* Must track the theme: a hardcoded dark value left a black bar across the
     light theme. color-mix keeps it translucent over whatever is behind it. */
  background: color-mix(in srgb, var(--background-default) 84%, transparent);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--border-primary);
}
/* Fallback for browsers without color-mix(). */
@supports not (background: color-mix(in srgb, red 50%, transparent)) {
  .site-header { background: var(--background-default); }
}
.site-header .wrap {
  display: flex; align-items: center; gap: 16px;
  min-height: var(--nav-h);
}
.brand {
  display: flex; align-items: center; gap: 10px;
  font-family: var(--font-mono); font-size: 13px; letter-spacing: 0.06em;
  color: var(--primary-main); text-transform: uppercase;
}
.brand:hover { color: var(--primary-light); }
/* The mark is the owner's own parallelogram, traced to SVG. It replaced an "AM"
   monogram, which the owner asked to remove: a wordmark repeating its own
   initials next to the name said nothing. */
.brand .mark {
  width: 22px; height: 22px; flex: none; display: block;
}
.brand .mark svg { display: block; width: 100%; height: 100%; }
nav.site-nav { margin-left: auto; display: flex; align-items: center; gap: 2px; }
nav.site-nav a {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-secondary);
  padding: 8px 12px;
  border-radius: 4px;
  transition: color 0.15s ease, background 0.15s ease;
}
nav.site-nav a:hover { color: var(--primary-light); background: var(--secondary-main); }
nav.site-nav a[aria-current="page"] { color: var(--text-primary); }

/* ---------------------------------------------------------------- buttons */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.08em;
  text-transform: uppercase; font-weight: 400;
  padding: 13px 22px; border-radius: 5px; cursor: pointer;
  border: 1px solid var(--border-secondary);
  background: transparent; color: var(--primary-main);
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
  white-space: nowrap;
}
.btn:hover { background: var(--secondary-main); color: var(--primary-light); border-color: var(--border-secondary); }
.btn-primary {
  background: var(--primary-main); color: var(--primary-contrastText);
  border-color: var(--primary-main);
}
.btn-primary:hover { background: var(--primary-light); color: var(--primary-contrastText); }
.btn-sm { padding: 8px 14px; font-size: 11px; }

/* ---------------------------------------------------------------- hero
   Mirrors the reference's landing shape: enormous whitespace, one line drawing,
   minimal text. The dark radial wash and the 4px scanline overlay that used to
   sit behind this were removed, because R-07 requires a stated visual-identity
   purpose for a background pattern and there was none. Nothing is lost: the
   line drawing carries the weight. */
.hero {
  padding: clamp(64px, 10vw, 116px) 0 clamp(56px, 8vw, 96px);
  position: relative;
  border-bottom: 1px solid var(--border-primary);
}
.hero .wrap { position: relative; z-index: 1; }

/* one focal point per screen: the animated drawing, centred, with the text beneath */
.hero-motif {
  display: block;
  width: min(560px, 82vw);
  height: clamp(230px, 34vw, 320px);
  margin: 0 auto clamp(30px, 4.5vw, 48px);
}
.hero-motif canvas { display: block; width: 100%; height: 100%; }

.hero-name {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-secondary);
  margin: 0 0 16px;
}

.eyebrow {
  display: inline-flex; align-items: center; gap: 9px;
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--text-secondary);
  border: 1px solid var(--border-primary); border-radius: 100px;
  padding: 6px 14px; margin-bottom: 24px;
  background: var(--background-default);
}
.status-dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--success-main); flex: none;
}
h1.display {
  font-size: clamp(2rem, 5.6vw, 3.6rem);
  font-weight: 400;
  letter-spacing: -0.032em;
  line-height: 1.06;
  max-width: 22ch;
}
h1.display .accent { color: var(--text-primary); }
.hero .lede {
  color: var(--text-secondary);
  font-size: clamp(1rem, 1.5vw, 1.1rem);
  max-width: 58ch;
  margin-top: 22px;
}
.hero .lede strong { color: var(--text-primary); font-weight: 500; }
.actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 32px; }

/* ---------------------------------------------------------------- sections */
section { padding: clamp(56px, 8vw, 104px) 0; border-top: 1px solid var(--border-primary); }
section:first-of-type { border-top: 0; }

.sec-head { margin-bottom: 44px; max-width: 70ch; }
.sec-num {
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--text-secondary);
  display: block; margin-bottom: 16px;
}
.sec-head h2 { font-size: clamp(1.5rem, 3.2vw, 2.35rem); font-weight: 400; }
.sec-head p { color: var(--text-secondary); margin-top: 16px; }

/* ---------------------------------------------------------------- grids */
.grid { display: grid; gap: 1px; background: var(--border-primary); border: 1px solid var(--border-primary); }
.grid-2 { grid-template-columns: repeat(2, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }

.cell {
  background: var(--background-default);
  padding: 28px 26px;
  transition: background 0.18s ease;
}
.cell:hover { background: var(--secondary-main); }
.cell .n {
  font-family: var(--font-mono); font-size: 11px; color: var(--text-secondary);
  display: block; margin-bottom: 14px; letter-spacing: 0.1em;
}
.cell h3 { font-size: 1.02rem; margin-bottom: 9px; font-weight: 500; }
.cell p { color: var(--text-secondary); font-size: 0.9rem; margin: 0; }

/* ---------------------------------------------------------------- stats strip */
.stats { display: grid; grid-template-columns: repeat(4, 1fr); border: 1px solid var(--border-primary); }
.stat { padding: 22px 24px; border-right: 1px solid var(--border-primary); }
.stat:last-child { border-right: 0; }
.stat .k {
  font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--text-secondary); display: block; margin-bottom: 9px;
}
.stat .v { font-size: 1.05rem; color: var(--primary-main); }
.stat .v.mono { font-family: var(--font-mono); font-size: 0.92rem; }

/* ---------------------------------------------------------------- panel */
.panel {
  border: 1px solid var(--border-primary);
  background: var(--secondary-main);
  padding: 30px;
  border-radius: 5px;
}
.panel h3 { display: flex; align-items: center; gap: 10px; margin-bottom: 16px; font-size: 1.05rem; }
.panel ul { margin: 0; padding-left: 18px; color: var(--text-secondary); font-size: 0.93rem; }
.panel li { margin-bottom: 8px; }
.panel li strong { color: var(--text-primary); font-weight: 400; }

.chips { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 22px; }
.chip {
  font-family: var(--font-mono); font-size: 10.5px; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--text-secondary);
  border: 1px solid var(--border-primary); border-radius: 4px;
  padding: 5px 9px; background: var(--background-default);
}
.chip.on { color: var(--text-primary); border-color: var(--border-secondary); }

/* ---------------------------------------------------------------- facts */
.facts { border: 1px solid var(--border-primary); }
.fact { display: flex; gap: 20px; padding: 15px 22px; border-bottom: 1px solid var(--border-primary); }
.fact:last-child { border-bottom: 0; }
.fact .k {
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--text-secondary);
  min-width: 160px; flex: none; padding-top: 3px;
}
.fact .v { color: var(--text-primary); font-size: 0.95rem; }
.fact .v a { color: var(--accent); }
.fact .v a:hover { color: var(--primary-light); }

/* ---------------------------------------------------------------- wallets */
.wallet-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1px; background: var(--border-primary); border: 1px solid var(--border-primary); }
.wallet {
  background: var(--background-default);
  padding: 22px 24px;
  display: flex; flex-direction: column; gap: 12px;
  transition: background 0.18s ease;
}
.wallet:hover { background: var(--secondary-main); }
.wallet-top { display: flex; align-items: center; gap: 10px; }

/* network brand mark, inlined as SVG so nothing is fetched at runtime */
.net-logo { flex: none; width: 22px; height: 22px; display: block; }
.net-logo-fallback { border-radius: 6px; }

/* === payment network marks (generated) === */
/* brand colour: the dark-theme default for every mark */
.net-logo-solana { color: #9945FF; }
.net-logo-ethereum { color: #8A92B2; }
.net-logo-base { color: #0052FF; }
.net-logo-polygon { color: #7B3FE4; }
.net-logo-bnb { color: #F0B90B; }
.net-logo-bitcoin { color: #F7931A; }
.net-logo-hyperevm { color: #97FCE4; }
.net-logo-mail { color: #292929; }
.net-logo-threads { color: #292929; }
.net-logo-instagram { color: #292929; }
.net-logo-github { color: #292929; }
.tech-logo-nextjs { color: #ffffff; }
.tech-logo-react { color: #61DAFB; }
.tech-logo-typescript { color: #3178C6; }
.tech-logo-prisma { color: #8899a6; }
.tech-logo-mysql { color: #4479A1; }

/* darkened same-hue variants, for the light theme */
@media (prefers-color-scheme: light) {
  :root:not([data-theme]) .net-logo-solana { color: #7d2fd6; }
  :root:not([data-theme]) .net-logo-ethereum { color: #5a6488; }
  :root:not([data-theme]) .net-logo-base { color: #0043cc; }
  :root:not([data-theme]) .net-logo-polygon { color: #6631c4; }
  :root:not([data-theme]) .net-logo-bnb { color: #b98e08; }
  :root:not([data-theme]) .net-logo-bitcoin { color: #d78017; }
  :root:not([data-theme]) .net-logo-hyperevm { color: #3f8b7c; }
  :root:not([data-theme]) .net-logo-mail { color: #292929; }
  :root:not([data-theme]) .net-logo-threads { color: #292929; }
  :root:not([data-theme]) .net-logo-instagram { color: #292929; }
  :root:not([data-theme]) .net-logo-github { color: #292929; }
  :root:not([data-theme]) .tech-logo-nextjs { color: #000000; }
  :root:not([data-theme]) .tech-logo-react { color: #469db5; }
  :root:not([data-theme]) .tech-logo-typescript { color: #3178C6; }
  :root:not([data-theme]) .tech-logo-prisma { color: #2D3748; }
  :root:not([data-theme]) .tech-logo-mysql { color: #4479A1; }
}
:root[data-theme='light'] .net-logo-solana { color: #7d2fd6; }
:root[data-theme='light'] .net-logo-ethereum { color: #5a6488; }
:root[data-theme='light'] .net-logo-base { color: #0043cc; }
:root[data-theme='light'] .net-logo-polygon { color: #6631c4; }
:root[data-theme='light'] .net-logo-bnb { color: #b98e08; }
:root[data-theme='light'] .net-logo-bitcoin { color: #d78017; }
:root[data-theme='light'] .net-logo-hyperevm { color: #3f8b7c; }
:root[data-theme='light'] .net-logo-mail { color: #292929; }
:root[data-theme='light'] .net-logo-threads { color: #292929; }
:root[data-theme='light'] .net-logo-instagram { color: #292929; }
:root[data-theme='light'] .net-logo-github { color: #292929; }
:root[data-theme='light'] .tech-logo-nextjs { color: #000000; }
:root[data-theme='light'] .tech-logo-react { color: #469db5; }
:root[data-theme='light'] .tech-logo-typescript { color: #3178C6; }
:root[data-theme='light'] .tech-logo-prisma { color: #2D3748; }
:root[data-theme='light'] .tech-logo-mysql { color: #4479A1; }
:root[data-theme='dark'] .net-logo-solana { color: #9945FF; }
:root[data-theme='dark'] .net-logo-ethereum { color: #8A92B2; }
:root[data-theme='dark'] .net-logo-base { color: #0052FF; }
:root[data-theme='dark'] .net-logo-polygon { color: #7B3FE4; }
:root[data-theme='dark'] .net-logo-bnb { color: #F0B90B; }
:root[data-theme='dark'] .net-logo-bitcoin { color: #F7931A; }
:root[data-theme='dark'] .net-logo-hyperevm { color: #97FCE4; }
:root[data-theme='dark'] .net-logo-mail { color: #292929; }
:root[data-theme='dark'] .net-logo-threads { color: #292929; }
:root[data-theme='dark'] .net-logo-instagram { color: #292929; }
:root[data-theme='dark'] .net-logo-github { color: #292929; }
:root[data-theme='dark'] .tech-logo-nextjs { color: #ffffff; }
:root[data-theme='dark'] .tech-logo-react { color: #61DAFB; }
:root[data-theme='dark'] .tech-logo-typescript { color: #3178C6; }
:root[data-theme='dark'] .tech-logo-prisma { color: #8899a6; }
:root[data-theme='dark'] .tech-logo-mysql { color: #4479A1; }
/* Per-network tint rules are injected here by tools/build.mjs from
   src/assets/logos.js, which tools/build-logos.mjs generates. Do not hand-edit:
   each mark needs a brand colour plus a light-theme variant that clears WCAG's
   3.0 contrast threshold on white. */

.wallet .net { font-size: 0.98rem; color: var(--primary-main); }
.wallet .tick {
  font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.1em;
  color: var(--text-secondary); border: 1px solid var(--border-primary);
  border-radius: 3px; padding: 2px 6px; text-transform: uppercase;
}
.wallet .chain-id {
  margin-left: auto; font-family: var(--font-mono); font-size: 10px; color: var(--text-secondary);
}
.addr {
  font-family: var(--font-mono); font-size: 12.5px; line-height: 1.55;
  color: var(--text-primary);
  background: var(--background-paper);
  border: 1px solid var(--border-primary);
  border-radius: 4px;
  padding: 11px 13px;
  word-break: break-all;
  display: block;
  /* long EVM addresses must never be silently truncated when copied by hand */
  white-space: pre-wrap;
}
.wallet .note { color: var(--text-secondary); font-size: 0.84rem; margin: 0; }
.wallet-actions { display: flex; align-items: center; gap: 8px; margin-top: auto; }
.copy-btn {
  font-family: var(--font-mono); font-size: 10.5px; letter-spacing: 0.08em;
  text-transform: uppercase; padding: 7px 12px; cursor: pointer;
  background: var(--secondary-light); color: var(--primary-main);
  border: 1px solid var(--border-secondary); border-radius: 4px;
  transition: background 0.15s ease, color 0.15s ease;
}
.copy-btn:hover { background: var(--text-primary); color: var(--background-default); border-color: var(--text-primary); }
.copy-btn.done { background: var(--success-main); border-color: var(--success-main); color: #000; }
.wallet-actions .lnk {
  font-family: var(--font-mono); font-size: 10.5px; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--text-secondary); margin-left: auto;
}
.wallet-actions .lnk:hover { color: var(--accent); }

/* QR: rendered locally from the address, never via a third-party service */
.wallet-body { display: flex; gap: 16px; align-items: flex-start; }
.wallet-body .addr-wrap { min-width: 0; flex: 1; }
.qr {
  flex: none; width: 96px; height: 96px; padding: 6px;
  background: #fff; border: 1px solid var(--border-primary); border-radius: 4px;
  image-rendering: pixelated;
}
.qr svg { display: block; width: 100%; height: 100%; }
@media (max-width: 420px) { .qr { width: 76px; height: 76px; } }

/* chain grouping label */
.chain-tag {
  font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--info-main);
  border: 1px solid rgba(167, 125, 255, 0.35); border-radius: 3px; padding: 2px 6px;
}

.alert {
  border: 1px solid var(--warning-main);
  border-left-width: 3px;
  background: rgba(241, 223, 56, 0.05);
  padding: 16px 20px; border-radius: 4px;
  color: var(--text-primary); font-size: 0.9rem;
  margin-bottom: 28px;
}
.alert strong { color: var(--warning-main); font-weight: 500; }

/* ---------------------------------------------------------------- contact */
.contact-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1px; background: var(--border-primary); border: 1px solid var(--border-primary); }
.contact-card {
  background: var(--background-default);
  padding: 24px;
  display: flex; align-items: center; gap: 16px;
  transition: background 0.18s ease;
}
.contact-card:hover { background: var(--secondary-main); }
.contact-card .ic {
  width: 38px; height: 38px; flex: none; border-radius: 5px;
  border: 1px solid var(--border-primary); background: var(--background-default);
  display: grid; place-items: center;
}
/* The channel marks are UI chrome rather than brand colour, so they take the
   page ink and follow the theme instead of fighting it. */
.contact-card .ic svg { width: 17px; height: 17px; display: block; color: var(--text-primary); }
.contact-card:hover .ic { border-color: var(--border-secondary); }
.contact-card .lbl { color: var(--primary-main); font-size: 0.96rem; display: block; }
.contact-card .hdl { font-family: var(--font-mono); font-size: 11.5px; color: var(--text-secondary); }
.contact-card .arrow { margin-left: auto; color: var(--text-secondary); font-family: var(--font-mono); }
.contact-card:hover .arrow { color: var(--accent); }

/* ---------------------------------------------------------------- code / pre */
pre {
  background: var(--background-paper);
  border: 1px solid var(--border-primary);
  border-radius: 5px;
  padding: 18px 20px;
  overflow-x: auto;
  font-size: 12.5px;
  line-height: 1.75;
  color: var(--text-primary);
}
pre code { background: none; border: 0; padding: 0; font-size: inherit; }
code {
  font-family: var(--font-mono); font-size: 0.87em;
  background: var(--secondary-light);
  border: 1px solid var(--border-primary);
  border-radius: 3px; padding: 0.1em 0.38em;
  color: var(--accent);
}

/* ---------------------------------------------------------------- machine endpoints */
.endpoints { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; background: var(--border-primary); border: 1px solid var(--border-primary); }
.endpoint { background: var(--background-default); padding: 20px 22px; }
.endpoint .path {
  font-family: var(--font-mono); font-size: 12.5px; color: var(--accent);
  display: block; margin-bottom: 8px;
}
.endpoint .desc { color: var(--text-secondary); font-size: 0.85rem; }

/* ---------------------------------------------------------------- faq */
.faq { border: 1px solid var(--border-primary); border-bottom: 0; }
.faq:last-of-type { border-bottom: 1px solid var(--border-primary); }
.faq summary {
  cursor: pointer; list-style: none;
  padding: 19px 22px;
  font-size: 0.98rem; color: var(--primary-main);
  display: flex; justify-content: space-between; gap: 16px; align-items: center;
  transition: background 0.15s ease;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary:hover { background: var(--secondary-main); }
.faq summary::after { content: '+'; font-family: var(--font-mono); color: var(--text-secondary); flex: none; }
.faq[open] summary::after { content: '\2212'; color: var(--text-secondary); }
.faq .a { padding: 0 22px 20px; color: var(--text-secondary); font-size: 0.92rem; }
.faq .a p:last-child { margin-bottom: 0; }

/* ---------------------------------------------------------------- prose (subpages) */
.prose { padding: clamp(48px, 7vw, 84px) 0; }
.prose h1 { font-size: clamp(1.9rem, 5vw, 3rem); font-weight: 400; letter-spacing: -0.03em; margin-bottom: 18px; }
.prose h2 { font-size: clamp(1.25rem, 2.6vw, 1.7rem); font-weight: 400; margin: 52px 0 16px; }
.prose h3 { font-size: 1.05rem; margin: 28px 0 10px; }
.prose .lede { color: var(--text-secondary); font-size: 1.05rem; max-width: 62ch; }
.prose p, .prose li { color: var(--text-secondary); }
.prose strong { color: var(--text-primary); font-weight: 400; }
.prose a { color: var(--accent); }
.prose a:hover { color: var(--primary-light); }
.prose table { width: 100%; border-collapse: collapse; font-size: 0.9rem; margin: 18px 0; }
.prose th, .prose td { text-align: left; padding: 12px 14px; border-bottom: 1px solid var(--border-primary); }
.prose th {
  font-family: var(--font-mono); font-size: 10.5px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--text-secondary); font-weight: 400;
}

/* ---------------------------------------------------------------- footer */
.site-footer { border-top: 1px solid var(--border-primary); padding: 44px 0 56px; }
.site-footer .top { display: flex; flex-wrap: wrap; gap: 20px; align-items: baseline; }
.site-footer .name { font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.06em; text-transform: uppercase; }
.site-footer .links { margin-left: auto; display: flex; flex-wrap: wrap; gap: 4px; }
.site-footer .links a {
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--text-secondary); padding: 6px 10px;
}
.site-footer .links a:hover { color: var(--accent); }
.site-footer .agent-line {
  margin-top: 26px; padding-top: 20px; border-top: 1px solid var(--border-primary);
  font-family: var(--font-mono); font-size: 11px; color: var(--text-secondary);
  word-break: break-word;
}
.site-footer .agent-line a { color: var(--text-secondary); }
.site-footer .agent-line a:hover { color: var(--accent); }
.site-footer .copy { margin-top: 14px; font-size: 12px; color: var(--text-secondary); }

/* ---------------------------------------------------------------- responsive */
@media (max-width: 1024px) {
  .grid-4 { grid-template-columns: repeat(2, 1fr); }
  .endpoints { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 820px) {
  .grid-3 { grid-template-columns: repeat(2, 1fr); }
  .stats { grid-template-columns: repeat(2, 1fr); }
  .stat:nth-child(2) { border-right: 0; }
  .stat:nth-child(1), .stat:nth-child(2) { border-bottom: 1px solid var(--border-primary); }
}
@media (max-width: 700px) {
  :root { --gutter: 18px; }
  nav.site-nav { gap: 0; }
  nav.site-nav a { padding: 7px 8px; font-size: 11px; letter-spacing: 0.06em; }
  /* The brand name stays. Hiding it here was how the "AM" mark ended up as the
     only clickable home link on small screens, which is not a usable label. */
  .grid-2, .grid-3, .grid-4, .wallet-grid, .contact-grid, .endpoints { grid-template-columns: 1fr; }
  .facts .fact { flex-direction: column; gap: 4px; }
  .fact .k { min-width: 0; }
  h1.display { font-size: clamp(1.85rem, 8.6vw, 2.6rem); }
  .panel { padding: 22px; }
}
@media (max-width: 420px) {
  .stats { grid-template-columns: 1fr; }
  .stat { border-right: 0; border-bottom: 1px solid var(--border-primary); }
  .actions .btn { width: 100%; }
}

@media print {
  .site-header, .actions, .copy-btn { display: none; }
  body { background: #fff; color: #000; }
  .addr { background: #f4f4f4; color: #000; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  body { animation: none; }
  * { transition: none !important; }
}

/* ============================================================================
   DOCS SHELL
   Three columns, modelled on bittensor.com/docs which was measured rather than
   copied by eye: header sticky, 256px sticky sidebar, 704px reading column, and
   a 224px sticky rail listing the current page's headings.

   The type scale is deliberately small and mostly two sizes (26px heading, 15px
   body). That restraint is most of what makes the reference read as calm, so it
   is kept rather than dressed up.
   ============================================================================ */
.docs { padding: 0; }
.docs-inner {
  max-width: 1280px;
  margin: 0 auto;
  padding: 0 20px;
  display: grid;
  grid-template-columns: 256px minmax(0, 1fr) 224px;
  gap: 28px;
  align-items: start;
}
/* Pages with fewer than two h2s get no rail, and the column collapses rather
   than leaving a 224px hole. */
.docs-inner.no-rail { grid-template-columns: 256px minmax(0, 1fr); }

/* ------------------------------------------------------------- sidebar */
.docs-sidebar {
  position: sticky;
  top: calc(var(--nav-h) + 20px);
  max-height: calc(100vh - var(--nav-h) - 40px);
  overflow-y: auto;
  padding: 28px 0 40px;
}
.docs-search {
  display: flex; align-items: center; gap: 8px;
  border: 1px solid var(--border-primary);
  border-radius: 5px;
  padding: 0 10px;
  margin-bottom: 20px;
  color: var(--text-secondary);
}
.docs-search input {
  flex: 1; min-width: 0;
  border: 0; background: transparent; outline: none;
  font-family: var(--font-sans); font-size: 13px;
  color: var(--text-primary);
  padding: 9px 0;
}
.docs-search input::placeholder { color: var(--text-secondary); }
.docs-search:focus-within { border-color: var(--border-secondary); }

.docs-nav { font-size: 13px; }
.docs-nav ul { list-style: none; margin: 0 0 18px; padding: 0; }
.docs-nav-label {
  font-family: var(--font-mono);
  font-size: 10.5px; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--text-secondary);
  margin: 0 0 8px;
}
.docs-nav a {
  display: block;
  padding: 5px 0 5px 12px;
  border-left: 2px solid transparent;
  color: var(--text-secondary);
  text-decoration: none;
}
.docs-nav a:hover { color: var(--text-primary); }
/* The active item is marked by a left rule, as in the reference, rather than by
   colour alone. */
.docs-nav a.active {
  border-left-color: var(--text-primary);
  color: var(--text-primary);
}
/* Hidden by the sidebar filter. */
.docs-nav li[hidden] { display: none; }

/* -------------------------------------------------------------- article */
.docs-main { min-width: 0; padding: 40px 0 72px; }
.docs-article { max-width: 44rem; }
.docs-article h1 {
  font-size: 26px;
  font-weight: 500;
  letter-spacing: -0.015em;
  line-height: 1.25;
  margin: 0;
}
.docs-intro {
  font-size: 15px;
  color: var(--text-secondary);
  margin: 12px 0 0;
  max-width: 62ch;
}

/* Markdown body */
.docs-article h2 {
  font-size: 15px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-primary);
  margin: 44px 0 14px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border-primary);
}
.docs-article h3 { font-size: 15px; font-weight: 500; margin: 28px 0 8px; }
.docs-article h4 { font-size: 14px; font-weight: 500; margin: 22px 0 8px; }
.docs-article p,
.docs-article li { font-size: 15px; line-height: 1.65; color: var(--text-primary); }
.docs-article p { margin: 0 0 15px; }
.docs-article ul, .docs-article ol { margin: 0 0 18px; padding-left: 20px; }
.docs-article li { margin-bottom: 6px; }
.docs-article a { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }
.docs-article a:hover { color: var(--text-primary); }
.docs-article strong { font-weight: 550; }
.docs-article code {
  font-family: var(--font-mono); font-size: 0.88em;
  background: var(--secondary-main);
  border: 1px solid var(--border-primary);
  border-radius: 3px;
  padding: 1px 5px;
}
.docs-article pre {
  background: var(--secondary-main);
  border: 1px solid var(--border-primary);
  border-radius: 5px;
  padding: 14px 16px;
  overflow-x: auto;
  margin: 0 0 18px;
}
.docs-article pre code {
  background: none; border: 0; padding: 0;
  font-size: 12.5px; line-height: 1.6;
}
.docs-article blockquote {
  margin: 0 0 18px;
  padding: 2px 0 2px 16px;
  border-left: 2px solid var(--border-secondary);
  color: var(--text-secondary);
}
.docs-article blockquote p { margin: 0; color: var(--text-secondary); }
.docs-article hr { border: 0; border-top: 1px solid var(--border-primary); margin: 32px 0; }
.table-wrap { overflow-x: auto; margin: 0 0 20px; }
.docs-article table { border-collapse: collapse; width: 100%; font-size: 14px; }
.docs-article th, .docs-article td {
  border-bottom: 1px solid var(--border-primary);
  padding: 8px 12px 8px 0;
  text-align: left;
  vertical-align: top;
}
.docs-article th { font-weight: 500; color: var(--text-secondary); }
/* No white-space: nowrap on cells. It was set on headers only, which made a
   two-column fact table wider than a phone and pushed the document to 432px on
   a 414px viewport. Cells wrap instead, and .table-wrap scrolls if a table still
   cannot fit. */
@media (min-width: 560px) {
  .docs-article th { white-space: nowrap; }
}

/* ------------------------------------------------------- "where to go" cards
   The reference's index grid: label plus one line, two columns. */
.cards {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1px;
  background: var(--border-primary);
  border: 1px solid var(--border-primary);
  border-radius: 4px;
  overflow: hidden;
  margin: 0 0 24px;
}
.card {
  display: block;
  background: var(--background-default);
  padding: 16px 18px;
  text-decoration: none;
}
.card:hover { background: var(--secondary-main); }
.card-label {
  display: block;
  font-family: var(--font-mono); font-size: 10.5px;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--text-primary);
  margin-bottom: 6px;
}
.card-blurb { display: block; font-size: 13.5px; line-height: 1.5; color: var(--text-secondary); }

/* ----------------------------------------------------------- right rail */
.docs-rail {
  position: sticky;
  top: calc(var(--nav-h) + 20px);
  padding: 40px 0;
  font-size: 13px;
}
.docs-rail-label {
  font-family: var(--font-mono); font-size: 10.5px;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--text-secondary);
  margin: 0 0 10px;
}
.docs-rail ul { list-style: none; margin: 0; padding: 0; }
.docs-rail li { margin-bottom: 5px; }
.docs-rail a { color: var(--text-secondary); text-decoration: none; }
.docs-rail a:hover { color: var(--text-primary); text-decoration: underline; }

/* -------------------------------------------------------- narrow screens */
/* -------------------------------------------------------- narrow screens
   Every rule that overrides a two-class selector above must also be two classes
   deep, or it loses on specificity and the layout silently fails to collapse. */
@media (max-width: 1080px) {
  .docs-inner, .docs-inner.no-rail { grid-template-columns: 232px minmax(0, 1fr); }
  .docs-rail { display: none; }
  /* Must match .page-home .docs-inner above. */
  .page-home .docs-inner { grid-template-columns: 232px minmax(0, 1fr); }
  .page-home .docs-main { max-width: none; }
}
@media (max-width: 760px) {
  .docs-inner, .docs-inner.no-rail { grid-template-columns: minmax(0, 1fr); }
  /* Must match .page-home .docs-inner above: without this the home page kept a
     three-column grid on a phone and the article collapsed to zero width. */
  .page-home .docs-inner { grid-template-columns: minmax(0, 1fr); }
  .docs-sidebar {
    position: static; max-height: none; overflow: visible;
    padding: 20px 0 0;
    border-bottom: 1px solid var(--border-primary);
  }
  .docs-main { padding: 24px 0 56px; }
  .docs-article h1 { font-size: 23px; }
  .cards { grid-template-columns: minmax(0, 1fr); }
}

/* ------------------------------------------------------------ small header
   Five nav items plus the toggle need 348px, which does not fit a 414px phone
   and pushed the whole document 70px wide. The sidebar already carries the full
   navigation on every page, so here the header keeps the brand, the toggle, and
   the single link a reader is most likely to want. */
@media (max-width: 620px) {
  nav.site-nav a { display: none; }
  nav.site-nav a[href='/contact.html'] { display: inline-block; }
  .brand { font-size: 12px; letter-spacing: 0.04em; }
}

/* Long unbroken content must scroll or break inside its own box rather than
   widening the document. The contact page's request template is the case that
   caught this: a <pre> of fixed-width text is wider than a phone. */
.docs-article pre { max-width: 100%; }
.docs-article code { overflow-wrap: anywhere; }
/* --------------------------------------------------------- home page hero
   The animated hero needs more room than a 704px reading measure, so the main
   column is capped wider for the home page only. The prose below the hero stays
   at the reading width, because a 900px line of body text is unreadable.

   Note: there is deliberately NO `.page-home .docs-inner` rule here. It would
   only restate the grid already set on `.docs-inner`, and it is actively
   harmful: at two classes deep it outranks the single-class rules in the
   responsive block below, so at 414px the grid stayed three-column, .docs-main
   collapsed to 0px wide, and the content overflowed the document invisibly.
   Anything added here must be mirrored by an equally specific rule further down. */
.page-home .docs-main { max-width: 900px; }
.page-home .hero-motif {
  width: 100%;
  height: clamp(240px, 32vw, 340px);
  margin: 26px 0 40px;
}
@media (max-width: 1080px) {
  .page-home .docs-main { max-width: none; }
}
/* ------------------------------------------------- homepage payment tiles
   One tile per network with its own brand mark. Replaced a text list of
   addresses: those were unreadable at this size, and the network is what a
   reader scans for here. Addresses live on /payments.html and in payments.json. */
.net-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1px;
  background: var(--border-primary);
  border: 1px solid var(--border-primary);
  border-radius: 4px;
  overflow: hidden;
  margin: 0 0 20px;
}
.net-cell {
  display: flex; align-items: center; gap: 10px;
  background: var(--background-default);
  padding: 12px 14px;
  text-decoration: none;
  min-width: 0;
}
.net-cell:hover { background: var(--secondary-main); }
.net-cell svg { flex: none; width: 22px; height: 22px; display: block; }
.net-cell-text { min-width: 0; display: block; }
.net-cell-name {
  display: block;
  font-size: 13.5px;
  color: var(--text-primary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.net-cell-meta {
  display: block;
  font-family: var(--font-mono); font-size: 10.5px;
  letter-spacing: 0.04em; color: var(--text-secondary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.net-flag {
  margin-left: auto;
  font-family: var(--font-mono); font-size: 9.5px;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--warning-main);
  flex: none;
}
@media (max-width: 1080px) { .net-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 420px) { .net-grid { grid-template-columns: minmax(0, 1fr); } }
/* ------------------------------------------------------------ request form
   Six fields matching the request template, so a person filling this in and an
   agent POSTing JSON send the same shape. No CAPTCHA: it would lock out exactly
   the automated agents this form exists for, so spam is handled with a honeypot
   and server-side rate limiting instead. */
.req-form {
  border: 1px solid var(--border-primary);
  border-radius: 5px;
  padding: 22px;
  margin: 0 0 26px;
  background: var(--background-default);
}
.req-row { margin-bottom: 15px; }
.req-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 16px; }
.req-form label {
  display: block;
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-secondary);
  margin-bottom: 6px;
}
.req-opt { text-transform: none; letter-spacing: 0; opacity: 0.7; }
.req-form input,
.req-form select,
.req-form textarea {
  width: 100%;
  font-family: var(--font-sans);
  font-size: 14px;
  color: var(--text-primary);
  background: var(--background-default);
  border: 1px solid var(--border-secondary);
  border-radius: 4px;
  padding: 9px 11px;
}
.req-form textarea { resize: vertical; min-height: 84px; }
.req-form input::placeholder,
.req-form textarea::placeholder { color: var(--text-secondary); }
.req-form input:focus,
.req-form select:focus,
.req-form textarea:focus {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
  border-color: var(--accent);
}
.req-form button { margin-top: 6px; }
.req-note {
  font-size: 13px;
  color: var(--text-secondary);
  margin: 14px 0 0;
}
.req-status { font-size: 13px; margin: 12px 0 0; min-height: 1em; }
.req-status[data-state='ok'] { color: var(--success-main); }
.req-status[data-state='error'] { color: var(--error-main); }
/* Honeypot: removed from the flow entirely, but not with display:none, which
   some bots detect. Positioned off-screen instead. */
.req-hp {
  position: absolute;
  left: -9999px;
  width: 1px; height: 1px;
  overflow: hidden;
}
@media (max-width: 620px) {
  .req-grid { grid-template-columns: minmax(0, 1fr); }
  .req-form { padding: 18px; }
}
/* ---------------------------------------------------- shared-address networks
   Ethereum, Base, Polygon, BNB Chain and HyperEVM are one address, so they render
   as one card listing the networks rather than five identical cards. The chain ID
   is kept because a payer confirming on a specific chain needs it, and each name
   links to an explorer where one exists. */
.net-list {
  list-style: none;
  margin: 10px 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 6px 14px;
  font-size: 13px;
}
.net-list li {
  display: flex;
  align-items: baseline;
  gap: 6px;
  color: var(--text-secondary);
}
.net-list .lnk { color: var(--text-primary); }
.net-list .chain-id { font-family: var(--font-mono); font-size: 11px; color: var(--text-secondary); }
/* ------------------------------------------------------------- project cards
   Case studies on the Work page. They exist so the page shows evidence rather than
   only describing capability. There are deliberately no repository or live-system
   links: the proof is the problem, what was built, the stack and the outcome.
   A project without a screenshot renders no <figure> at all, so a pending screenshot
   cannot ship as a broken image. */
.proj-grid { display: grid; gap: 20px; margin: 0 0 30px; }
.proj {
  border: 1px solid var(--border-primary);
  border-radius: 5px;
  padding: 20px;
  background: var(--background-default);
}
.proj-head { margin-bottom: 12px; }
.proj-name { font-size: 18px; font-weight: 600; margin: 0 0 3px; letter-spacing: -0.01em; }
.proj-meta {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-secondary);
  margin: 0;
}
.proj-shot { margin: 0 0 16px; }
.proj-shot img {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--border-primary);
  border-radius: 4px;
}
.proj-detail { margin: 0; }
.proj-detail dt {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-secondary);
  margin-top: 14px;
}
.proj-detail dt:first-child { margin-top: 0; }
.proj-detail dd { margin: 5px 0 0; font-size: 14.5px; line-height: 1.65; }
.proj-stack {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 14px 0 0;
  padding: 0;
}
.proj-stack li {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-secondary);
  border: 1px solid var(--border-primary);
  border-radius: 3px;
  padding: 3px 8px;
}
.proj-outcome {
  margin: 14px 0 0;
  font-size: 14.5px;
  line-height: 1.65;
  padding-top: 12px;
  border-top: 1px solid var(--border-primary);
}
@media (max-width: 620px) {
  .proj { padding: 16px; }
}
/* The stack tags sat on the card's bottom border: a padded inline element needs its
   line box to grow, which line-height on the li does not do for an inline box. */
.proj-stack li {
  display: inline-flex;
  align-items: center;
  line-height: 1.5;
}
/* ------------------------------------------------------- featured work (home)
   The homepage used to carry a six-card grid linking to every page, which duplicated
   the sidebar and repeated a "What I do" heading. It now shows the work itself, which
   gives the page evidence rather than navigation, and links to the case studies. */
.feat-grid { display: grid; gap: 0; margin: 0 0 4px; border-top: 1px solid var(--border-primary); }
.feat {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 2fr) auto;
  gap: 4px 18px;
  align-items: baseline;
  padding: 15px 2px;
  border-bottom: 1px solid var(--border-primary);
  text-decoration: none;
  color: inherit;
}
.feat:hover { background: var(--background-subtle, rgba(0, 0, 0, 0.015)); }
.feat-name { font-size: 15.5px; font-weight: 600; letter-spacing: -0.01em; }
.feat-meta {
  grid-column: 1;
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-secondary);
}
.feat-built { grid-column: 2; grid-row: 1 / span 2; font-size: 14px; line-height: 1.6; }
.feat-stack {
  grid-column: 3;
  grid-row: 1 / span 2;
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: var(--text-secondary);
  white-space: nowrap;
  align-self: center;
}
@media (max-width: 760px) {
  .feat { grid-template-columns: minmax(0, 1fr); gap: 3px; }
  .feat-built, .feat-stack { grid-column: 1; grid-row: auto; }
  .feat-stack { white-space: normal; }
}
/* The three-column featured layout squeezed the description into a narrow column.
   Two columns read better: identity on the left, evidence on the right. */
.feat {
  grid-template-columns: minmax(180px, 1fr) minmax(0, 2.2fr);
  gap: 3px 22px;
}
.feat-built { grid-column: 2; grid-row: 1; }
.feat-stack { grid-column: 2; grid-row: 2; white-space: normal; align-self: start; }
.feat-name { grid-column: 1; grid-row: 1; }
.feat-meta { grid-column: 1; grid-row: 2; }
@media (max-width: 760px) {
  .feat-built, .feat-stack, .feat-name, .feat-meta { grid-column: 1; grid-row: auto; }
}
/* A project's public link, shown only where the owner approved one and it was checked
   with tools/assess-public-link.mjs. */
.proj-link { margin: 12px 0 0; font-size: 14px; }
.feat { display: grid; }
/* ------------------------------------------------------------------ venues
   Named, described, and linked where the link was verified. Naming real venues is
   the strongest proof on the page and it needs no screenshot. */
.venue-list { list-style: none; margin: 0 0 30px; padding: 0; border-top: 1px solid var(--border-primary); }
.venue-list li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr) auto;
  gap: 4px 18px;
  align-items: baseline;
  padding: 14px 2px;
  border-bottom: 1px solid var(--border-primary);
}
.venue-name { font-size: 15.5px; font-weight: 600; letter-spacing: -0.01em; }
.venue-detail { font-size: 14px; color: var(--text-secondary); line-height: 1.6; }
.venue-links { font-family: var(--font-mono); font-size: 11px; white-space: nowrap; }
.venue-links .lnk { margin-left: 10px; }
.proj-role {
  font-size: 13.5px;
  color: var(--text-secondary);
  margin: 4px 0 0;
}

/* ------------------------------------------------- homepage: the stack block
   The two products are halves of one system, so the homepage states the system once
   instead of listing two unrelated projects. */
.feat-stack-block { display: grid; grid-template-columns: minmax(160px, 1fr) minmax(0, 2.2fr); gap: 6px 22px; }
.feat-left { display: flex; flex-direction: column; gap: 3px; }
.feat-label { font-size: 15.5px; font-weight: 600; letter-spacing: -0.01em; }
.feat-right { display: flex; flex-direction: column; gap: 7px; }
.feat-parts { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.feat-parts li { font-size: 14px; line-height: 1.6; }
.feat-role { color: var(--text-secondary); }
.feat-where { font-size: 14px; line-height: 1.6; margin: 0; color: var(--text-secondary); }
@media (max-width: 760px) {
  .venue-list li { grid-template-columns: minmax(0, 1fr); }
  .venue-links { white-space: normal; }
  .venue-links .lnk:first-child { margin-left: 0; }
  .feat-stack-block { grid-template-columns: minmax(0, 1fr); }
}
/* ---------------------------------------------------- mobile navigation
   Below 760px the sidebar becomes a slide-in drawer, opened by the menu button in
   the header. It used to be poured into the top of the page instead, which buried
   the article under the whole navigation on a phone.

   The drawer hides only when <html> has the `js` class, set by an inline script
   before first paint. That matters for two reasons: with scripting disabled the
   navigation stays visible rather than being unreachable behind a dead button, and
   the sidebar does not flash open on load before the script runs. */
.menu-toggle { display: none; }

@media (max-width: 760px) {
  html.js .docs-sidebar {
    display: block;
    position: fixed;
    top: 0;
    left: 0;
    z-index: 60;
    width: 84vw;
    max-width: 300px;
    height: 100dvh;
    max-height: none;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 18px 18px 40px;
    margin: 0;
    background: var(--background-default);
    border-right: 1px solid var(--border-primary);
    transform: translateX(-102%);
    transition: transform 0.22s ease;
    will-change: transform;
  }
  html.js .docs-sidebar.is-open { transform: none; }

  /* Scrim over the page while the drawer is open. Tapping it closes the drawer, and
     it is a real button so it can be reached by keyboard as well as by finger. */
  html.js .nav-scrim {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 55;
    border: 0;
    padding: 0;
    background: rgba(0, 0, 0, 0.42);
    cursor: pointer;
  }
  html.js.nav-open { overflow: hidden; }

  /* The brand text plus the menu button do not fit alongside "Contact", which is the
     only link the header keeps at this width. The mark alone still identifies the
     site and still links home. */
  @media (max-width: 480px) {
    .brand .full { display: none; }
  }
}

/* The menu button. Hidden above 760px, where the sidebar is always visible. */
.menu-toggle {
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 0;
  margin-left: 4px;
  background: none;
  border: 1px solid var(--border-secondary);
  border-radius: 4px;
  cursor: pointer;
  color: var(--text-primary);
}
.menu-toggle:hover { border-color: var(--text-primary); }
.menu-bars,
.menu-bars::before,
.menu-bars::after {
  display: block;
  width: 16px;
  height: 1.5px;
  background: currentColor;
  transition: transform 0.2s ease, opacity 0.2s ease;
}
.menu-bars { position: relative; }
.menu-bars::before,
.menu-bars::after { content: ''; position: absolute; left: 0; }
.menu-bars::before { top: -5px; }
.menu-bars::after { top: 5px; }
/* Bars become a cross while the drawer is open. */
html.nav-open .menu-bars { background: transparent; }
html.nav-open .menu-bars::before { transform: translateY(5px) rotate(45deg); }
html.nav-open .menu-bars::after { transform: translateY(-5px) rotate(-45deg); }

@media (max-width: 760px) {
  .menu-toggle { display: inline-flex; }
}

/* While the drawer is open, clear the header of everything except the close button.
   Otherwise "Contact" and the theme toggle sat visibly on top of the scrim, right next
   to the X, which reads as three competing controls. */
html.js.nav-open .brand,
html.js.nav-open .site-nav > a,
html.js.nav-open .theme-toggle { visibility: hidden; }

/* The drawer's own scrollbar should not sit against the text. */
html.js .docs-sidebar { scrollbar-width: thin; }
html.js .docs-sidebar .docs-filter { margin-top: 2px; }
/* ------------------------------------------------- drawer header controls
   The header stays put while the drawer is open; nothing is moved into the drawer.

   An earlier attempt moved "Contact" and the theme toggle into the drawer so they
   would stay reachable, then hid them in the header. It worked, but a bare "Contact"
   heading appeared above the search box, which read as a mistake rather than a menu.
   Keeping the header static is simpler and leaves every control where a reader
   already expects it.

   Only the brand is hidden, because the drawer covers that corner anyway. */
html.js.nav-open .brand { visibility: hidden; }
/* The stack tags were touching the description above them. Measured on the live page:
   the gap between .proj-detail dd and .proj-stack was exactly 0px, on desktop and on a
   phone alike, because the list had no top margin while the text sat on its baseline.

   Each rule below is explicit about the side it controls, because this block has now
   been overridden twice and an inherited margin is what went missing. */
.proj-detail dd { margin: 5px 0 0; }
.proj-detail dd:last-of-type { margin-bottom: 0; }
.proj-stack { margin: 14px 0 18px; }
.proj-stack li { display: inline-flex; align-items: center; line-height: 1.5; }
.proj-outcome { margin-top: 16px; }
.proj-link { margin-top: 14px; }
/* The stack tags' own top margin kept collapsing to 0px.
   Measured on the live page: the rule `.proj-stack { margin: 14px 0 18px }` was present
   in the loaded stylesheet, yet getComputedStyle reported margin-top: 0px and the gap
   between the description and the tags was exactly 0px.

   Rather than keep fighting whichever rule wins, the space is put on the element ABOVE
   the list. A margin-bottom on the preceding box cannot be absorbed by a neighbouring
   margin, so this is deterministic rather than dependent on collapsing rules. */
.proj-detail dd:last-of-type { margin-bottom: 14px; }
.proj-stack { margin-top: 0; }
/* ------------------------------------------------------- technology marks
   Each stack tag carries the mark of the technology it names. The marks are tinted from
   the generated logo CSS, so they follow the theme without a second icon set. */
.proj-stack li {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  line-height: 1.5;
}
.tech-logo {
  display: block;
  flex: 0 0 auto;
  /* Brand marks carry their own colour, so nothing is inherited from the tag text. */
}
.tech-name { white-space: nowrap; }

/* ----------------------------------------------------------- product marks
   The two products' own icons, shown beside their names on the Work page and in the
   homepage list. Full colour, so they are not themed: a brand chip that recolours
   itself is no longer the brand. */
.proj-head { display: flex; align-items: flex-start; gap: 12px; }
.proj-heading { min-width: 0; }
.proj-mark { flex: 0 0 auto; display: block; line-height: 0; }
.app-logo {
  display: block;
  border-radius: 6px;
  /* The marks are square brand chips, so a hairline keeps a dark icon from bleeding
     into a dark background. */
  box-shadow: 0 0 0 1px var(--border-primary);
}
.feat-parts li { display: flex; align-items: center; gap: 8px; }
/* The product mark sat inside the header, so the product name and its metadata were
   indented to the icon's right edge and no longer lined up with the body text below.
   The mark is taken out of the flow instead: it sits in the margin, and the heading keeps
   the card's left edge. */
.proj-head { display: block; position: relative; padding-left: 0; }
.proj-mark {
  position: absolute;
  left: 0;
  top: 2px;
}
.proj-heading { padding-left: 42px; min-height: 28px; }
@media (max-width: 420px) {
  /* Not enough width for a hanging mark beside a wrapping heading. */
  .proj-mark { position: static; margin-bottom: 8px; }
  .proj-heading { padding-left: 0; }
}
/* The mark sits ABOVE the product name rather than beside it.
   Two earlier attempts put it in the flow beside the heading: first as a flex sibling, which
   indented the name and the metadata to the icon's right edge so they no longer lined up
   with the body text; then hanging into the margin, which reproduced the same misalignment.
   Stacking them removes the problem entirely: everything in the card now shares one left
   edge, which is what makes the block look deliberate. */
.proj-head { display: block; position: static; padding-left: 0; }
.proj-mark { position: static; margin: 0 0 10px; }
.proj-heading { padding-left: 0; min-height: 0; }