/* W-TAILWIND-SELFHOST-001: site.css is layered so Tailwind utilities win.
   Unlayered CSS always beats layered CSS, which made `.text-white` lose to
   the base `a{color:...}` and blanked button labels. Layer order matches
   Tailwind's own: theme, base, components, utilities. */
@import url("./theme.css") layer(base);
@import url("./content.css") layer(components);
@layer base {
/* Shared site chrome: one header, one footer, everywhere.
   Single source is scripts/site_chrome.py; this file is the paint. Class names
   are snav-* prefixed so page styles never clash with them. Works with or
   without Tailwind on the page, in light and dark, at 320px and up. */

/* W-ONE-WIDTH-ALL-001. THE container width, and the only one. It used to live
   in each page's own <style> (.shell at 80rem on home, 64 on how-it-works and
   use-cases, 62 on why and pricing, 52 on contact, 44 on news and blog via
   .wrap), so the site had five widths and a page could drift without a gate
   noticing. This is the single source; a page must not set its own width.
   `check_theme.py` enforces it. `.wrap` is an alias so the generated blog and
   news pages inherit the same width with no rule of their own.

   W-PROSE-MEASURE-001. 80rem is a layout width, not a reading width: at about
   16px Inter it is roughly 140 characters per line, well past the 65-75 a
   person reads comfortably. So there are exactly TWO named measures, declared
   here and nowhere else: `.shell`/`.wrap` (wide, 80rem) for grids, tables and
   dashboards, and `.prose` (40rem) for a column of sentences. A page picks a
   token, never a number. `--page-read` is the single value behind it. */
:root{--page-wide:80rem;--page-read:40rem}
.shell,.wrap{width:min(calc(100% - 40px),var(--page-wide));max-width:var(--page-wide);margin-inline:auto;padding-inline:0}
/* `.wrap.prose` (two classes) so the reading measure wins by specificity, not
   by source order. A page picks wide or reading; it never sets a number.

   W-SIGN-READING-WIDTH-001. Sign is a single focused action (link a wallet,
   sign). A full-width form reads as a wall on a normal window, so the sign page
   is the one documented exception: it uses the reading measure. The exception
   is declared here and allowed by name in `check_theme.py`, so it is a
   deliberate choice, not a page inventing a width. */
.wrap.prose{max-width:var(--page-read)}
@media(max-width:620px){.shell,.wrap{width:calc(100% - 28px)}}

/* W-ONE-THEME-ONE-NAV-001. THE palette, and the only one. Every page used to
   define its own :root with its own near-copy of these variables, so the site
   read as several sites and drifted page by page. A page must not define a
   theme: it links this file and that is the look. `scripts/check_theme.py`
   enforces it. The palette now lives in theme.css: Emerald is the default,
   and the shared toggle selects the saved light alternate. */
/* All palette roles and body typography come from theme.css. */
a{color:var(--accent-text)}
}

@layer components {

:focus-visible{outline:2px solid var(--accent-text);outline-offset:2px;border-radius:6px}
.snav-bar{position:sticky;top:0;z-index:50;
  background:var(--nav-bg,rgba(244,244,244,.86));
  border-bottom:1px solid var(--nav-border,#e0e0e0);
  backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px)}
[data-theme="dark"] .snav-bar{background:var(--nav-bg,rgba(13,17,23,.86));
  border-bottom-color:var(--nav-border,#30363d)}
.snav-inner{width:min(calc(100% - 40px),var(--page-wide));max-width:var(--page-wide);margin-inline:auto;padding:.75rem 0;
  display:flex;align-items:center;justify-content:space-between;gap:.75rem}
@media(max-width:620px){.snav-inner{width:calc(100% - 28px)}}
.snav-brand{font-size:var(--type-wordmark);font-weight:800;letter-spacing:-.02em;
  color:var(--text,#161616);text-decoration:none;white-space:nowrap}
.snav-brand b{color:var(--accent-text);font-weight:800}
.snav-links{display:none;align-items:center;gap:.25rem;font-size:.875rem}
@media(min-width:1024px){.snav-links{display:flex}}
/* W-NAV-FLAT-MENU-001: flat top-level links, an animated underline, a clear
   hover, and an active marker for the current page. No dropdowns, no subtext. */
.snav-links>a{position:relative;color:var(--text-secondary,#525252);
  text-decoration:none;padding:.45rem .7rem;border-radius:.5rem;
  transition:color .15s ease,background .15s ease}
.snav-links>a::after{content:"";position:absolute;left:.7rem;right:.7rem;
  bottom:.28rem;height:2px;border-radius:2px;background:currentColor;
  transform:scaleX(0);transform-origin:left;transition:transform .18s ease}
.snav-links>a:hover{color:var(--text,#161616);background:var(--accent-bg,var(--accent-bg))}
.snav-links>a:hover::after{transform:scaleX(1)}
.snav-links>a.is-active{color:var(--text,#161616);font-weight:650}
.snav-links>a.is-active::after{transform:scaleX(1);background:var(--accent-text)}
.snav-links>a:focus-visible{outline:2px solid var(--accent-text);outline-offset:2px}
/* Without scripting, show the links instead of controls that cannot open them. */
html:not(.js) .snav-tools{display:none}
@media(max-width:1023px){
  html:not(.js) .snav-inner{flex-wrap:wrap}
  html:not(.js) .snav-links{display:flex;flex-wrap:wrap;width:100%;gap:.25rem .5rem}
}
@media(prefers-reduced-motion:reduce){
  .snav-links>a,.snav-links>a::after{transition:none}
}
.snav-tools{display:flex;align-items:center;gap:.5rem}
.snav-toggle{width:46px;min-height:44px;border:0;background:none;border-radius:13px;
  cursor:pointer;position:relative;flex-shrink:0;padding:0;
  display:inline-flex;align-items:center;justify-content:center}
.snav-toggle::before{content:"";position:absolute;left:0;right:0;top:50%;height:25px;
  transform:translateY(-50%);border-radius:13px;
  border:1px solid var(--nav-border,#e0e0e0);background:#e3e6eb}
[data-theme="dark"] .snav-toggle::before{background:#30363d}
.snav-toggle .knob{position:absolute;top:11px;left:2px;width:21px;height:21px;
  border-radius:50%;background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.3);z-index:1}
.snav-burger{display:inline-flex;align-items:center;justify-content:center;
  width:44px;min-height:44px;border-radius:10px;cursor:pointer;
  border:1px solid var(--nav-border,#e0e0e0);background:none;
  color:var(--text,#161616)}
@media(min-width:1024px){.snav-burger{display:none}}
.snav-panel{display:none;border-top:1px solid var(--nav-border,#e0e0e0);
  max-height:70vh;overflow-y:auto}
.snav-panel.open{display:block}
@media(min-width:1024px){.snav-panel{display:none !important}}
/* Flat mobile panel: every page is a full-width row, active marked, hover and
   focus visible. No accordions, no subtext lines. */
.snav-panel>a{display:flex;align-items:center;min-height:48px;padding:.6rem 1rem;
  color:var(--text-secondary,#525252);text-decoration:none;font-weight:600;
  border-bottom:1px solid var(--nav-border,#e0e0e0);
  transition:background .15s ease,color .15s ease}
.snav-panel>a:hover{background:var(--accent-bg,var(--accent-bg));color:var(--text,#161616)}
.snav-panel>a.is-active{color:var(--accent-text)}
.snav-panel>a.is-active::before{content:"";width:3px;height:1.1rem;border-radius:2px;
  background:var(--accent-text);margin-right:.6rem}
.snav-panel>a:focus-visible{outline:2px solid var(--accent-text);outline-offset:-2px}
/* Breadcrumb under the shared header on generated pages. The header itself
   stays identical everywhere; this one line carries the back link. */
.snav-crumb{max-width:80rem;margin:0 auto;padding:.5rem 1rem;font-size:.82rem}
.snav-crumb .back{color:var(--text-secondary,#525252);text-decoration:none;
  display:inline-flex;align-items:center;min-height:44px}
/* Copy buttons on code blocks. Added by assets/site.js to every <pre>, so any
   page gets them without editing. Plain <pre> without JS is unchanged. */
/* The button gets its own band above the code (padding-top), never a right
   gutter. A right gutter only works while the line is short; one long command
   scrolls straight under the button and hides the tail of the command, which is
   the part a reader needs. A top band cannot be scrolled over. */
pre.snav-copyable{position:relative;padding-top:2.3rem}
/* W-CODE-WRAP-MOBILE-001: a long command on a phone ran past the right edge
   under the copy button, so the tail of the command was unreachable at 375px
   (setting up mintrr is exactly a long command). Code blocks wrap rather than
   clip, so the whole line is reachable on the narrowest screen. */
pre.snav-copyable{white-space:pre-wrap;overflow-wrap:anywhere}
.snav-copy{position:absolute;top:.4rem;right:.4rem;font-size:.68rem;font-weight:600;
  border:1px solid currentColor;border-radius:.45rem;padding:.3rem .6rem;
  background:rgba(0,0,0,.35);color:#fff;cursor:pointer;opacity:.85;min-height:32px}
.snav-copy:hover{opacity:1}
/* Shared footer. Same everywhere: brand line, link row, builder line. */
.snav-foot{border-top:1px solid var(--nav-border,#e0e0e0);margin-top:2rem;
  padding:2rem 0;font-size:.875rem;color:var(--text-secondary,#525252)}
.snav-foot .snav-inner{display:block}
.snav-foot .row{display:flex;flex-direction:column;align-items:center;gap:1rem}
@media(min-width:768px){.snav-foot .row{flex-direction:row;justify-content:space-between}}
.snav-foot nav{display:flex;flex-wrap:wrap;justify-content:center;gap:.25rem 1.25rem}
.snav-foot nav a{color:inherit;text-decoration:none;display:inline-block;padding-block:.6rem}
.snav-foot nav a:hover{color:var(--text,#161616)}
.snav-fine{margin-top:1rem;padding-top:1rem;border-top:1px solid var(--nav-border,#e0e0e0);
  display:flex;flex-direction:column;align-items:center;gap:.5rem;font-size:.75rem}
@media(min-width:640px){.snav-fine{flex-direction:row;justify-content:space-between}}
.snav-fine a{color:inherit}
/* Content column for reading pages (setup, sign). The header and footer are
   full-bleed like the home page; only the prose between them is narrow. Before
   this, those pages constrained <body> itself, so the shared header was trapped
   in a 42rem column and read as a different site. */

/* ---------------------------------------------------------------------------
   W-SHARED-COMPONENTS-001. THE components, and the only copy.

   Every page used to re-declare these in its own <style>: `.card` (5 variants,
   two radii, three shadows), `.section` (2/2.25/2.75/3rem), `.nav` (three
   backgrounds), `.kicker`, `.gradient`, `.code`, `.reveal`. That is why the
   pages did not read as one site. They are defined once here, and a page keeps
   only rules that are genuinely its own. site.css loads after a page's <style>
   block, so these win for any page that left a stale copy behind; the copies
   were removed anyway. `check_theme.py` counts page-owned copies so the drift
   cannot return.
   --------------------------------------------------------------------------- */
.card-highlight{border:2px solid transparent;background:linear-gradient(var(--card-bg),var(--card-bg)) padding-box,linear-gradient(135deg,var(--accent-text),var(--accent-text)) border-box}
.card{background:var(--card-bg);border:1px solid var(--card-border);border-radius:16px;box-shadow:var(--card-shadow);transition:transform .3s ease,box-shadow .3s ease,border-color .3s ease;padding:1.25rem}
.card:hover{box-shadow:var(--card-hover);transform:translateY(-3px)}
.card-static{transition:none}
.card-static:hover{box-shadow:var(--card-shadow);transform:none}
.kicker{font-size:.72rem;font-weight:700;text-transform:uppercase;letter-spacing:.09em;color:var(--accent-text);margin-bottom:.5rem}
.gradient{background:linear-gradient(120deg,var(--accent-text) 0%,var(--accent-text) 100%);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}
.code{background:var(--code-bg);color:var(--code-text);border-radius:12px;font-family:'JetBrains Mono',monospace}
.stat{font-size:clamp(1.9rem,6vw,2.6rem);font-weight:800;line-height:1;letter-spacing:-0.02em;font-variant-numeric:tabular-nums}
.badge{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;border-radius:999px;font-size:12px;font-weight:600;border:1px solid transparent}
.feature-icon{width:44px;height:44px;border-radius:12px;display:flex;align-items:center;justify-content:center;flex-shrink:0}
.section{padding-block:2.75rem}
.step-num{width:32px;height:32px;border-radius:50%;background:var(--accent-bg);color:var(--accent-text);display:flex;align-items:center;justify-content:center;font-weight:700;font-size:13px;flex-shrink:0}

/* One reveal animation, one definition. Every page repeated this with
   translateY 16px or 18px and a subtly different easing. Motion is off under
   prefers-reduced-motion, which is why the rule carries its own guard. */
.js .reveal{opacity:0;transform:translateY(18px);transition:opacity .6s cubic-bezier(.22,1,.36,1),transform .6s cubic-bezier(.22,1,.36,1);transition-delay:var(--d,0s)}
.reveal.in{opacity:1;transform:none}
@media(prefers-reduced-motion:reduce){.reveal{opacity:1;transform:none;transition:none}}
.noscript-reveal{opacity:1 !important;transform:none !important}
.snav-brand{display:inline-flex;align-items:center;gap:.45rem}
.snav-brand b{margin-left:-.45rem}
.snav-brand .brand-mark{width:22px;height:22px;flex-shrink:0}
.utility-page h2{font-size:clamp(1.3rem,3vw,1.8rem);line-height:1.25;letter-spacing:-.025em}
.utility-page .card+.card{margin-top:1rem}
.utility-page input{border-color:var(--bd-control);background:var(--surface-2);color:var(--fg)}
.utility-page input::placeholder{color:var(--fg-muted);opacity:1}
.utility-page .card:hover{transform:none;box-shadow:var(--card-shadow)}
.og-canvas{position:relative;width:1200px;height:630px;overflow:hidden}
.og-canvas>.snav-bar,.og-canvas>.snav-foot{display:none}

/* The homepage uses panel statistics; editorial pages use a number alone. */
.home-page .stat{font-size:inherit;font-weight:inherit;line-height:inherit;letter-spacing:inherit}
pre{background:var(--code);color:var(--code-text)}
@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms !important;animation-iteration-count:1 !important;transition-duration:.001ms !important;scroll-behavior:auto !important}
  .js .reveal{opacity:1;transform:none;transition:none}
}
@media(hover:none),(pointer:coarse){.card:hover{transform:none;box-shadow:var(--card-shadow)}}

}
