/* sdr-ui 0.9.0 — the shared look of Secure Data Research's sites. Source: securedataresearch/sdr-ui. */
@layer ui-tokens, ui-base, site-base, ui-components;
/* The two faces, self-hosted beside this sheet (SIL OFL 1.1). Relative URLs, so they resolve next to whichever copy of the
   bundle a page loads: the hosted /vX.Y.Z/ or a vendored copy. `optional`: a face not ready for the first paint waits for
   the next page instead of swapping in, so text never reflows. Sites preload instrument-sans.woff2 (see markup/head.html). */
@font-face { font-family: "Instrument Sans"; font-style: normal; font-weight: 400 700; font-display: optional; src: url(fonts/instrument-sans.woff2) format("woff2"); }
@font-face { font-family: "Instrument Sans"; font-style: italic; font-weight: 400 700; font-display: optional; src: url(fonts/instrument-sans-italic.woff2) format("woff2"); }
@font-face { font-family: "JetBrains Mono"; font-style: normal; font-weight: 400 700; font-display: optional; src: url(fonts/jetbrains-mono.woff2) format("woff2"); }
/* metric-matched stand-ins (sizes from fontTools against Arial / Liberation Sans): the fallback lays out the same lines */
@font-face { font-family: "Instrument Sans Fallback"; src: local("Arial"), local("Liberation Sans"), local("Helvetica Neue"); size-adjust: 102.97%; ascent-override: 94.2%; descent-override: 24.28%; line-gap-override: 0%; }
@font-face { font-family: "JetBrains Mono Fallback"; src: local("Menlo"), local("Consolas"), local("DejaVu Sans Mono"), local("Liberation Mono"); size-adjust: 100%; ascent-override: 102%; descent-override: 30%; line-gap-override: 0%; }

@layer ui-tokens {
/* generated from src/tokens/palette.json by tools/build.ts. Do not edit. */
:root {
  --ink: #0a0a0a;
  --ink-2: #171717;
  --ink-3: #262626;
  --g-700: #525252;
  --g-500: #737373;
  --g-300: #a3a3a3;
  --g-200: #d4d4d4;
  --g-100: #e5e5e5;
  --g-50: #f5f5f5;
  --white: #ffffff;
  --on-dark: #ffffff;
  --on-dark-2: rgb(255 255 255 / .8);
  --on-dark-3: rgb(255 255 255 / .62);
  --on-dark-line: rgb(255 255 255 / .24);
  --on-dark-fill: rgb(255 255 255 / .07);
  --banner-shade: rgb(10 10 10 / .62);
  --banner-shade-2: rgb(10 10 10 / .32);
  --banner-shade-0: rgb(10 10 10 / 0);
  --text-on-banner-shadow: 0 1px 2px rgb(0 0 0 / .4);
  --term-bg: #0a0a0a;
  --term-ink: #e5e5e5;
  --term-dim: #a3a3a3;
  --term-accent: #86b4e2;
  --emerald: #00694e;
  --red: #d4002a;
  --gold: #8f8750;
  --sapphire: #3f6d9c;
  --bg: #f3f4f0;
  --text-strong: #0b0c0c;
  --text: #1b1c1c;
  --muted: #4c4e4c;
  --faint: #5f615e;
  --line: rgb(16 20 18 / .08);
  --line-2: rgb(16 20 18 / .15);
  --rule: #a5a8a3;
  --tint: rgb(16 20 18 / .035);
  --fill: #e9eae5;
  --accent: #3c6997;
  --accent-soft: #e6edf4;
  --on-accent: #ffffff;
  --ok: #00694e;
  --wait: #6f6838;
  --bad: #d4002a;
  --surface: rgb(255 255 255 / .62);
  --surface-hi: rgb(255 255 255 / .8);
  --surface-solid: #fbfbf9;
  --edge: rgb(255 255 255 / .85);
  --shadow: 0 1px 2px rgb(16 20 18 / .05), 0 8px 24px -10px rgb(16 20 18 / .14);
  --shadow-lift: 0 2px 6px rgb(16 20 18 / .07), 0 22px 44px -18px rgb(16 20 18 / .26);
  --banner-edge: 0 1px 2px rgb(0 0 0 / .12), 0 24px 48px -24px rgb(0 0 0 / .45);
  --mesh: radial-gradient(56% 42% at 6% -4%, rgb(0 105 78 / .13), transparent 72%), radial-gradient(48% 40% at 100% 6%, rgb(64 112 160 / .13), transparent 70%), radial-gradient(60% 46% at 74% 104%, rgb(160 152 96 / .14), transparent 72%), radial-gradient(40% 34% at 0% 92%, rgb(64 112 160 / .07), transparent 70%);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --emerald: #43b592;
    --red: #ff6079;
    --gold: #d3c68a;
    --sapphire: #86b4e2;
    --bg: #0c0e10;
    --text-strong: #f6f6f3;
    --text: #e2e3df;
    --muted: #b3b5b0;
    --faint: #9a9d97;
    --line: rgb(255 255 255 / .08);
    --line-2: rgb(255 255 255 / .16);
    --rule: #5a5e62;
    --tint: rgb(255 255 255 / .045);
    --fill: #121417;
    --accent: #86b4e2;
    --accent-soft: #18222d;
    --on-accent: #0c0e10;
    --ok: #43b592;
    --wait: #d3c68a;
    --bad: #ff6079;
    --surface: rgb(26 29 33 / .58);
    --surface-hi: rgb(36 40 45 / .78);
    --surface-solid: #16191c;
    --edge: rgb(255 255 255 / .07);
    --shadow: 0 1px 2px rgb(0 0 0 / .35), 0 12px 32px -14px rgb(0 0 0 / .6);
    --shadow-lift: 0 2px 6px rgb(0 0 0 / .4), 0 26px 50px -18px rgb(0 0 0 / .75);
    --banner-edge: inset 0 0 0 1px rgb(255 255 255 / .07), 0 24px 48px -24px rgb(0 0 0 / .8);
    --mesh: radial-gradient(56% 42% at 6% -4%, rgb(0 105 78 / .30), transparent 72%), radial-gradient(48% 40% at 100% 6%, rgb(64 112 160 / .22), transparent 70%), radial-gradient(60% 46% at 74% 104%, rgb(160 152 96 / .12), transparent 72%), radial-gradient(40% 34% at 0% 92%, rgb(64 112 160 / .12), transparent 70%);
  }
}
:root[data-theme="dark"] {
  --emerald: #43b592;
  --red: #ff6079;
  --gold: #d3c68a;
  --sapphire: #86b4e2;
  --bg: #0c0e10;
  --text-strong: #f6f6f3;
  --text: #e2e3df;
  --muted: #b3b5b0;
  --faint: #9a9d97;
  --line: rgb(255 255 255 / .08);
  --line-2: rgb(255 255 255 / .16);
  --rule: #5a5e62;
  --tint: rgb(255 255 255 / .045);
  --fill: #121417;
  --accent: #86b4e2;
  --accent-soft: #18222d;
  --on-accent: #0c0e10;
  --ok: #43b592;
  --wait: #d3c68a;
  --bad: #ff6079;
  --surface: rgb(26 29 33 / .58);
  --surface-hi: rgb(36 40 45 / .78);
  --surface-solid: #16191c;
  --edge: rgb(255 255 255 / .07);
  --shadow: 0 1px 2px rgb(0 0 0 / .35), 0 12px 32px -14px rgb(0 0 0 / .6);
  --shadow-lift: 0 2px 6px rgb(0 0 0 / .4), 0 26px 50px -18px rgb(0 0 0 / .75);
  --banner-edge: inset 0 0 0 1px rgb(255 255 255 / .07), 0 24px 48px -24px rgb(0 0 0 / .8);
  --mesh: radial-gradient(56% 42% at 6% -4%, rgb(0 105 78 / .30), transparent 72%), radial-gradient(48% 40% at 100% 6%, rgb(64 112 160 / .22), transparent 70%), radial-gradient(60% 46% at 74% 104%, rgb(160 152 96 / .12), transparent 72%), radial-gradient(40% 34% at 0% 92%, rgb(64 112 160 / .12), transparent 70%);
}
/* The tokens that are not colours: faces, sizes, radii, layout, motion. Colours are in palette.json (tokens.css). */
:root {
  --sans: "Instrument Sans", "Instrument Sans Fallback", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: "JetBrains Mono", "JetBrains Mono Fallback", ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  /* body size: a document reads at 17px; a dense app sets --body-size on its own :root (pipe 15px, negotiator 14px) */
  --body-size: 17px;
  --body-leading: 1.6;

  /* layout: --wrap is the page's widest line, --measure the reading column (rem, so a heading and its text share it) */
  --wrap: 1680px;
  --gutter: clamp(16px, 4vw, 32px);
  --measure: 49rem;

  /* corners: cards, then small things (code, tiles, inputs), then the banner */
  --radius: 20px;
  --radius-s: 12px;
  --radius-xs: 6px;
  --radius-banner: 28px;
  --pill: 999px;

  --blur: saturate(160%) blur(18px);

  /* motion: things ease out as they arrive and ease in as they leave; hover is fast, arrival medium, leaving quicker */
  --ease-out: cubic-bezier(.2, .8, .2, 1);
  --ease-in: cubic-bezier(.4, 0, 1, 1);
  --t-fast: 160ms;
  --t-in: 240ms;
  --t-out: 90ms;
  --t-slow: 450ms;
  /* the banner's drift: a long, even breath */
  --ease-drift: cubic-bezier(.45, 0, .55, 1);
}

/* generated: src/components/cloth.svg */
:root { --ui-cloth: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' preserveAspectRatio='none'%3E%3Cdefs%3E%3Cfilter id='soft' x='-30%' y='-30%' width='160%' height='160%'%3E%3CfeGaussianBlur stdDeviation='5.5'/%3E%3C/filter%3E%3Cfilter id='mid' x='-30%' y='-30%' width='160%' height='160%'%3E%3CfeGaussianBlur stdDeviation='2.4'/%3E%3C/filter%3E%3Cfilter id='crisp' x='-30%' y='-30%' width='160%' height='160%'%3E%3CfeGaussianBlur stdDeviation='.9'/%3E%3C/filter%3E%3C/defs%3E%3Crect width='100' height='100' fill='%23090a0c'/%3E%3Cpath filter='url(%23soft)' fill='%230b4a3a' opacity='.85' d='M-46 120 C -38 70, -10 48, -10 -10 L 24 -10 C 24 48, -4 70, -12 120 Z'/%3E%3Cpath filter='url(%23soft)' fill='%2307080a' opacity='.9' d='M-10 120 C -2 70, 26 48, 26 -10 L 40 -10 C 40 48, 12 70, 4 120 Z'/%3E%3Cpath filter='url(%23soft)' fill='%231d3f66' opacity='1' d='M2 120 C 10 70, 38 48, 38 -10 L 70 -10 C 70 48, 42 70, 34 120 Z'/%3E%3Cpath filter='url(%23mid)' fill='%233b6fa8' opacity='.9' d='M11 120 C 19 70, 47 48, 47 -10 L 61 -10 C 61 48, 33 70, 25 120 Z'/%3E%3Cpath filter='url(%23crisp)' fill='%238fb9e6' opacity='.55' d='M18 120 C 26 70, 54 48, 54 -10 L 56.5 -10 C 56.5 48, 28.5 70, 20.5 120 Z'/%3E%3Cpath filter='url(%23soft)' fill='%2308100f' opacity='.85' d='M32 120 C 40 70, 68 48, 68 -10 L 78 -10 C 78 48, 50 70, 42 120 Z'/%3E%3Cpath filter='url(%23soft)' fill='%230d5a46' opacity='.9' d='M42 120 C 50 70, 78 48, 78 -10 L 102 -10 C 102 48, 74 70, 66 120 Z'/%3E%3Cpath filter='url(%23mid)' fill='%231f7a62' opacity='.7' d='M49 120 C 57 70, 85 48, 85 -10 L 93 -10 C 93 48, 65 70, 57 120 Z'/%3E%3Cpath filter='url(%23crisp)' fill='%237fd0b6' opacity='.35' d='M52.5 120 C 60.5 70, 88.5 48, 88.5 -10 L 90 -10 C 90 48, 62 70, 54 120 Z'/%3E%3Cpath filter='url(%23soft)' fill='%2307080a' opacity='.75' d='M70 120 C 78 70, 106 48, 106 -10 L 150 -10 C 150 48, 122 70, 114 120 Z'/%3E%3Cpath filter='url(%23soft)' fill='%232c5f93' opacity='.55' d='M84 -10 L 120 -10 L 120 22 C 106 24, 94 14, 84 -10 Z'/%3E%3Cellipse filter='url(%23soft)' cx='94' cy='92' rx='14' ry='10' fill='%238f8750' opacity='.18'/%3E%3C/svg%3E"); }
}
@layer ui-base {
/* The page itself: reset, type, the mesh, focus, the one reduced-motion rule, page-change motion. Element selectors only
   where every SDR page agrees (box-sizing, body, focus, selection); nothing here styles a site's own classes. */
*, *::before, *::after { box-sizing: border-box; }
html { color-scheme: light dark; background: var(--bg); scroll-behavior: smooth; scrollbar-gutter: stable; -webkit-text-size-adjust: 100%; }
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"] { color-scheme: dark; }
body {
  margin: 0; min-height: 100vh; background: transparent; color: var(--text);
  font-family: var(--sans); font-size: var(--body-size); line-height: var(--body-leading);
  -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility;
  font-variant-numeric: tabular-nums;
}
/* the mesh on its own fixed layer: identical on every page, so a page change cross-fades content over a ground that holds still */
body::before { content: ""; position: fixed; inset: 0; z-index: -1; background: var(--mesh), var(--bg); pointer-events: none; }
code, pre, kbd, samp { font-family: var(--mono); font-variant-ligatures: none; }
h1, h2, h3 { font-variant-numeric: proportional-nums; }
/* links take their text's colour; each component decides how a link is marked (underline, weight, a pill) */
a { color: inherit; }
::selection { background: color-mix(in oklab, var(--accent) 28%, transparent); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: var(--radius-xs); }
[hidden] { display: none !important; }

/* .ui-wrap: the page's column, centred, with the gutter */
.ui-wrap { max-width: var(--wrap); margin-inline: auto; padding-inline: var(--gutter); }
/* screen-reader-only text */
.ui-sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* page changes (transitions.js / boot.js): the old page eases out, then the new one eases in, never both in one frame; the
   transition layer shows the same ground, and the top bar and banner hold still. Opt in with @view-transition (head.html). */
::view-transition { background: var(--mesh), var(--bg); }
::view-transition-group(root), ::view-transition-group(ui-topbar) { animation: none; }
::view-transition-image-pair(root) { isolation: auto; }
::view-transition-old(root) { mix-blend-mode: normal; animation: ui-page-out var(--t-out) var(--ease-in) both; }
::view-transition-new(root) { mix-blend-mode: normal; animation: ui-page-in var(--t-in) var(--ease-out) 60ms both; }
::view-transition-old(ui-topbar) { display: none; }
::view-transition-new(ui-topbar) { animation: none; }
::view-transition-group(ui-banner) { animation-duration: var(--t-in); animation-timing-function: var(--ease-out); }
::view-transition-old(ui-banner), ::view-transition-new(ui-banner) { animation-duration: var(--t-in); }
@keyframes ui-page-out { to { opacity: 0; } }
@keyframes ui-page-in { from { opacity: 0; transform: translateY(6px); } }
/* the same change where cross-document view transitions are missing: boot.js sets html.ui-nvt, and html.ui-arriving only
   when a same-site link led here (transitions.js .ui-leaving). Never on a first visit, so the first paint is the page. */
html.ui-nvt.ui-arriving .ui-page { animation: ui-page-in var(--t-in) var(--ease-out) both; }
html.ui-nvt.ui-leaving .ui-page { animation: ui-page-out var(--t-out) var(--ease-in) both; }

/* the one reduced-motion rule: nothing moves, and everything still arrives. Durations collapse to nothing rather than
   animations being removed, so anything that starts hidden and animates in (a reveal, a fade) lands in its end state. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important; animation-delay: 0s !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; transition-delay: 0s !important; }
  ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; }
}

}
@layer ui-components {
/* ui-banner: the head of a page, a rounded card of cloth on ink. The same picture in both themes, on every page, at every
   size: the cloth (cloth.svg) is vector, inlined by the build as --ui-cloth, and laid out relative to the banner, so the
   first paint is the final paint and a phone gets the same composition as a monitor. One element, named for the view
   transition, so a page change holds it in place.

     <header class="ui-banner ui-banner--head">
       <div class="ui-banner-inner">
         <p class="ui-eyebrow">…</p>  <h1>…</h1>  <p class="ui-lead">…</p>
         <p class="ui-actions">…</p>  or  <nav class="ui-tabs">…</nav>
       </div>
     </header>

   Variants: --hero (the home page's, taller, bigger type), --head (an inner page), --ask (a call to action, no min height).

   The cloth drifts, very slowly: a layer a little larger than the banner, carrying the drawing, moved and scaled by a
   transform only (the compositor moves it; the drawing is never repainted). Its resting position is the first keyframe,
   so the first paint, a paused tab and reduced motion (base.css collapses the animation and it returns to rest) all show
   the same picture. */
.ui-banner {
  position: relative; isolation: isolate; overflow: hidden;
  display: flex; align-items: flex-end;
  min-height: clamp(300px, 38vh, 400px);
  margin-block: clamp(12px, 2vw, 20px) 0;
  border-radius: var(--radius-banner);
  color: var(--on-dark);
  background: var(--ink);
  box-shadow: var(--banner-edge);
  view-transition-name: ui-banner;
  /* type is sized from the banner's own width (cqi), so every size keeps the same proportions */
  container-type: inline-size;
}
/* the cloth, on its own layer: 4% of slack on every side covers the drift (at most 2.5% sideways, 1.5% down, 3% larger) */
.ui-banner::before {
  content: ""; position: absolute; inset: -4%; z-index: -2; pointer-events: none;
  background: var(--ui-cloth) 0 0 / 100% 100% no-repeat;
  animation: ui-drift 48s var(--ease-drift) infinite alternate;
  will-change: transform;
}
@keyframes ui-drift { to { transform: translate3d(-2.5%, 1.5%, 0) scale(1.03); } }
/* the headline's quiet: ink pooled on the left, where the words sit */
.ui-banner::after {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: linear-gradient(90deg, var(--banner-shade) 0%, var(--banner-shade-2) 52%, var(--banner-shade-0) 82%);
}
.ui-banner-inner { position: relative; width: 100%; padding: clamp(24px, 5cqi, 60px); }
.ui-banner :is(h1, h2, .ui-lead, .ui-eyebrow) { max-width: 760px; text-shadow: var(--text-on-banner-shadow); }
.ui-banner h1 { margin: 0 0 .3em; color: var(--on-dark); font-weight: 600; text-wrap: balance; font-size: clamp(30px, 8cqi, 56px); line-height: 1.04; overflow-wrap: break-word; hyphens: manual; letter-spacing: -.035em; }
.ui-banner h2 { margin: 0 0 14px; color: var(--on-dark); font-weight: 600; text-wrap: balance; font-size: clamp(24px, 4.6cqi, 40px); line-height: 1.1; letter-spacing: -.03em; }
.ui-banner .ui-lead { margin: 0; color: var(--on-dark-2); font-size: clamp(16px, 2.4cqi, 20px); line-height: 1.5; text-wrap: pretty; }
.ui-banner .ui-eyebrow { color: var(--on-dark-3); }
.ui-banner .ui-actions { margin-top: 28px; }
.ui-banner .ui-tabs { margin-top: 22px; }
.ui-banner a:not([class]) { color: var(--on-dark); }

.ui-banner--hero { min-height: clamp(420px, 58vh, 560px); }
.ui-banner--hero h1 { font-size: clamp(36px, 9cqi, 80px); line-height: 1; letter-spacing: -.04em; margin-bottom: 20px; }
.ui-banner--hero .ui-lead { max-width: 36em; }
.ui-banner--ask { min-height: 0; }
.ui-banner--ask .ui-lead { font-size: 18px; max-width: 34em; }
/* a second banner on one page must not share the view-transition name */
.ui-banner--ask { view-transition-name: none; }

/* the eyebrow: a small mono label above a heading, anywhere */
.ui-eyebrow { font-family: var(--mono); font-size: 12.5px; letter-spacing: .06em; text-transform: uppercase; color: var(--faint); margin-block: 0 14px; }

/* ui-topbar: frosted, sticky, the same element on every page (named for the view transition, so it holds still).

     <div class="ui-topbar"><header class="ui-top">
       <a class="ui-brand" href="/"><img class="ui-mask" src="mark.png" alt="" width="36" height="36">
         <span class="ui-brand-long">Secure Data Research, LLC</span><span class="ui-brand-short">SDR</span></a>
       <nav class="ui-links" aria-label="Main">
         <a href="/a/" aria-current="page">A</a> <a class="ui-optional" href="/b/">B</a> <a class="ui-cta" href="…">Email us</a>
       </nav>
     </header></div>

   .ui-mask: a white-mask logo, drawn as ink on the light bar and as white on the dark one. A full-colour mark omits it.
   .ui-optional links hide below 860px; the short brand name replaces the long one below 1180px. */
.ui-topbar { position: sticky; top: 0; z-index: 10; view-transition-name: ui-topbar; border-bottom: 1px solid var(--line); background: color-mix(in oklab, var(--bg) 92%, transparent); }
@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .ui-topbar { background: color-mix(in oklab, var(--bg) 62%, transparent); -webkit-backdrop-filter: var(--blur); backdrop-filter: var(--blur); }
}
.ui-top { display: flex; align-items: center; justify-content: space-between; gap: 16px; max-width: var(--wrap); margin-inline: auto; padding: 12px var(--gutter); color: var(--text-strong); }
.ui-brand { display: inline-flex; align-items: center; gap: 12px; text-decoration: none; color: var(--text-strong); font-weight: 600; font-size: 19px; letter-spacing: -.015em; }
.ui-brand img { width: 36px; height: 36px; border-radius: 9px; }
.ui-brand img.ui-mask { filter: brightness(0); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .ui-brand img.ui-mask { filter: none; } }
:root[data-theme="dark"] .ui-brand img.ui-mask { filter: none; }
.ui-brand-short { display: none; }
.ui-links { display: flex; flex-wrap: wrap; gap: 4px 6px; align-items: center; font-size: 15px; }
.ui-links a { text-decoration: none; color: var(--muted); padding: 7px 12px; border-radius: var(--pill); transition: background var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out); }
.ui-links a:hover { color: var(--text-strong); background: var(--tint); }
.ui-links a[aria-current] { color: var(--text-strong); background: var(--tint); box-shadow: inset 0 0 0 1px var(--line); }
.ui-links .ui-cta { color: var(--bg); background: var(--text-strong); margin-left: 6px; }
.ui-links .ui-cta:hover { color: var(--bg); background: var(--text-strong); transform: translateY(-1px); box-shadow: var(--shadow); }
@media (max-width: 1180px) { .ui-brand:has(.ui-brand-short) .ui-brand-long { display: none; } .ui-brand-short { display: inline; } }
@media (max-width: 860px) { .ui-links .ui-optional { display: none; } }
@media (max-width: 640px) {
  .ui-top { gap: 8px; } .ui-links { gap: 2px; font-size: 14px; flex-wrap: nowrap; }
  .ui-links a { padding: 6px 8px; white-space: nowrap; } .ui-links .ui-cta { margin-left: 2px; }
  .ui-brand { gap: 8px; font-size: 16px; } .ui-brand img { width: 28px; height: 28px; }
}
@media (max-width: 359px) { .ui-top { padding-inline: 10px; gap: 4px; } .ui-links { font-size: 12.5px; } .ui-links a { padding: 5px 4px; } }

/* ui-section: a band of a page with a big heading and an optional muted note under it.
     <section class="ui-section ui-wrap"><h2 class="ui-section-title">How an engagement goes.</h2> … </section> */
.ui-section { padding-block: clamp(48px, 7vw, 88px) 0; }
.ui-section-title { margin-block: 0 14px; font-size: clamp(28px, 3.6vw, 40px); line-height: 1.1; letter-spacing: -.03em; font-weight: 600; color: var(--text-strong); text-wrap: balance; max-width: 22em; }
.ui-section-note { color: var(--muted); max-width: 46em; margin-block: 0 24px; }
.ui-section-note a { color: var(--text-strong); }

/* ui-btn: a pill. --primary is ink (the page colour as its text), --ghost is glass with a hairline, --quiet is text on a
   tint, --small shrinks any of them. On a banner they invert to read on ink. Works on <a> and <button>.
     <p class="ui-actions"><a class="ui-btn ui-btn--primary" href="…">Start</a> <a class="ui-btn ui-btn--ghost" href="…">More</a></p> */
.ui-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px; max-width: 100%;
  padding: 13px 22px; border: 1px solid transparent; border-radius: var(--pill); cursor: pointer;
  font: inherit; font-weight: 600; font-size: 15.5px; line-height: 1; text-align: center; text-decoration: none;
  color: var(--text-strong); background: transparent;
  transition: transform var(--t-fast) var(--ease-out), box-shadow var(--t-fast) var(--ease-out), background var(--t-fast) var(--ease-out), border-color var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out);
}
.ui-btn:hover:not(:disabled) { transform: translateY(-1px); }
.ui-btn:active:not(:disabled) { transform: translateY(0) scale(.985); }
.ui-btn:disabled, .ui-btn[aria-disabled="true"] { opacity: .5; cursor: default; }
.ui-btn--primary { background: var(--text-strong); color: var(--bg); box-shadow: var(--shadow); }
.ui-btn--primary:hover:not(:disabled) { box-shadow: var(--shadow-lift); }
.ui-btn--ghost { border-color: var(--line-2); background: var(--surface); -webkit-backdrop-filter: var(--blur); backdrop-filter: var(--blur); }
.ui-btn--ghost:hover:not(:disabled) { border-color: var(--text-strong); }
.ui-btn--quiet { color: var(--muted); }
.ui-btn--quiet:hover:not(:disabled) { color: var(--text-strong); background: var(--tint); transform: none; }
.ui-btn--danger { color: var(--bad); border-color: color-mix(in oklab, var(--bad) 45%, transparent); }
.ui-btn--danger:hover:not(:disabled) { border-color: var(--bad); }
.ui-btn--small { padding: 7px 13px; font-size: 13.5px; }
.ui-btn--block { display: flex; width: 100%; }
.ui-banner .ui-btn--primary { background: var(--on-dark); color: var(--ink); }
.ui-banner .ui-btn--ghost { color: var(--on-dark); border-color: var(--on-dark-line); background: var(--on-dark-fill); }
.ui-banner .ui-btn--ghost:hover { border-color: var(--on-dark); }
.ui-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-block: 0; }

/* ui-card: the one glass recipe, a solid surface where the browser cannot frost. --lift raises it on hover (for a card
   that is a link), --flat drops the glass for dense surfaces (tables, app panes).
     <article class="ui-card"><p class="ui-label">Step 1</p><h3>…</h3><p>…</p></article> */
.ui-card { background: var(--surface-solid); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow); padding: 24px 24px 22px; }
@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .ui-card:not(.ui-card--flat) { background: var(--surface); -webkit-backdrop-filter: var(--blur); backdrop-filter: var(--blur); box-shadow: inset 0 1px 0 var(--edge), var(--shadow); }
}
.ui-card--lift { transition: transform var(--t-fast) var(--ease-out), box-shadow var(--t-fast) var(--ease-out); text-decoration: none; color: inherit; display: block; }
.ui-card--lift:hover { transform: translateY(-2px); box-shadow: inset 0 1px 0 var(--edge), var(--shadow-lift); }
.ui-card--flat { background: var(--surface-solid); }
.ui-card--tight { padding: 14px 16px; border-radius: var(--radius-s); }
.ui-card > :first-child { margin-top: 0; }
.ui-card > :last-child { margin-bottom: 0; }
.ui-card h3 { margin: 8px 0; font-size: 19px; letter-spacing: -.015em; font-weight: 600; color: var(--text-strong); }
.ui-card p { color: var(--muted); font-size: 15.5px; }
/* a grid of cards that reflows from four to one */
.ui-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr)); gap: 16px; }
/* the small mono label: a card's kicker, a table's caption */
.ui-label { font-family: var(--mono); font-size: 11.5px; letter-spacing: .06em; text-transform: uppercase; color: var(--faint); margin-block: 0; }
/* a card's trailing link, and its meta line */
.ui-card .ui-more { display: inline-block; margin-top: 16px; font-size: 14px; color: var(--text-strong); font-weight: 600; text-decoration: none; }
.ui-card .ui-more:hover { text-decoration: underline; }
.ui-card .ui-meta { color: var(--faint); font-size: 14px; margin-block: 0 8px; }

/* ui-tabs: a row of pills for the pages of one group (or one control's options). The current one is filled.
     <nav class="ui-tabs" aria-label="Results"><a href="/r/" aria-current="page">Overview</a><a href="/r/ladder/">Ladder</a></nav> */
.ui-tabs { display: flex; flex-wrap: wrap; gap: 8px; margin-block: 0; padding: 0; }
.ui-tabs a, .ui-tabs button { font: inherit; font-size: 14.5px; line-height: 1; padding: 9px 14px; border-radius: var(--pill); border: 1px solid var(--line-2); background: var(--surface); color: var(--text); text-decoration: none; cursor: pointer;
  transition: border-color var(--t-fast) var(--ease-out), background var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out); }
.ui-tabs a:hover, .ui-tabs button:hover { border-color: var(--text-strong); }
.ui-tabs [aria-current], .ui-tabs [aria-selected="true"], .ui-tabs [aria-pressed="true"] { background: var(--text-strong); color: var(--bg); border-color: var(--text-strong); font-weight: 600; }
.ui-banner .ui-tabs a, .ui-banner .ui-tabs button { color: var(--on-dark); border-color: var(--on-dark-line); background: var(--on-dark-fill); }
.ui-banner .ui-tabs a:hover, .ui-banner .ui-tabs button:hover { border-color: var(--on-dark); }
.ui-banner .ui-tabs [aria-current], .ui-banner .ui-tabs [aria-selected="true"] { color: var(--ink); background: var(--on-dark); border-color: var(--on-dark); }
@media (max-width: 640px) { .ui-tabs { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; margin-inline: calc(-1 * var(--gutter)); padding-inline: var(--gutter); } .ui-tabs a { white-space: nowrap; } }

/* ui-prose: a document. It spans the page column; each child caps itself at the reading measure and centres, so a wide
   child (a figure, a long table) simply opts out with .ui-wide: no viewport arithmetic, no sideways scroll. Children set
   only block margins, so the centring holds.
     <article class="ui-prose"><h1>…</h1><p>…</p><pre><code>…</code></pre><table>…</table></article> */
:where(.ui-figure) { margin-inline: 0; }
.ui-prose { padding-block: clamp(36px, 5vw, 64px); }
:where(.ui-prose) > * { max-width: var(--measure); margin-inline: auto; }
:where(.ui-prose) > .ui-wide { max-width: none; }
/* a document headed by its banner: the banner sits where the prose would start, with room under it */
.ui-prose:has(> .ui-banner:first-child) { padding-top: 0; }
:where(.ui-prose) > .ui-banner { max-width: none; margin-block-end: clamp(32px, 4vw, 52px); }
/* ui-prose--data: a data page. The text keeps the reading measure; everything else (tables, charts, sections of
   figures) takes the full width of the page column, so a wide table is never squeezed into a reading column. */
:where(.ui-prose--data) > * { max-width: none; }
:where(.ui-prose--data > :is(p, ul, ol, h1, h2, h3, h4, blockquote, dl, pre, .ui-lede, .ui-note, .ui-kv, .ui-label, .ui-disclosure)),
:where(.ui-prose--data > section > :is(p, ul, ol, h2, h3, h4, .ui-note)) { max-width: var(--measure); margin-inline: auto; }
:where(.ui-prose) h1 { font-size: clamp(32px, 4.4vw, 46px); letter-spacing: -.035em; line-height: 1.08; margin-block: 0 .5em; color: var(--text-strong); font-weight: 600; text-wrap: balance; }
:where(.ui-prose) h2 { font-size: clamp(22px, 2.6vw, 28px); letter-spacing: -.025em; line-height: 1.15; margin-block: 2em .6em; color: var(--text-strong); font-weight: 600; text-wrap: balance; }
:where(.ui-prose) h3 { font-size: 19px; letter-spacing: -.015em; margin-block: 1.6em .5em; color: var(--text-strong); font-weight: 600; }
/* the section label: a small mono heading, per heading (h2.ui-label) or for a whole document whose headings come from
   Markdown and cannot carry a class (.ui-prose--labels) */
:where(.ui-prose) h2.ui-label, :where(.ui-prose--labels) h2 { font-family: var(--mono); font-size: 12.5px; letter-spacing: .06em; text-transform: uppercase; color: var(--faint); margin-block: 2.2em .7em; font-weight: 500; }
:where(.ui-prose) p { margin-block: 0 1.1em; }
:where(.ui-prose) strong { color: var(--text-strong); font-weight: 600; }
:where(.ui-prose) ul, :where(.ui-prose) ol { padding-left: 1.2em; margin-block: 0 1.1em; }
:where(.ui-prose) li { margin: .35em 0; }
:where(.ui-prose) a:not([class]) { color: inherit; text-decoration-color: var(--rule); text-underline-offset: 3px; transition: text-decoration-color var(--t-fast) var(--ease-out); }
:where(.ui-prose) a:not([class]):hover { text-decoration-color: var(--text-strong); }
:where(.ui-prose) hr { border: 0; border-top: 1px solid var(--line-2); margin-block: 2.4em; }
:where(.ui-prose) blockquote { margin-block: 1.2em; padding: .2em 0 .2em 1.1em; border-left: 3px solid var(--line-2); color: var(--muted); }
:where(.ui-prose) img, :where(.ui-prose) svg, :where(.ui-prose) video { max-width: 100%; height: auto; }
.ui-lede { font-size: clamp(19px, 2.1vw, 22px); line-height: 1.5; color: var(--text); }

/* code: a block on a tint, an inline chip, one size relationship */
:where(.ui-prose) pre, .ui-pre { font-family: var(--mono); font-size: .88em; line-height: 1.5; background: var(--tint); border: 1px solid var(--line); border-radius: var(--radius-s); padding: 16px 18px; overflow-x: auto; margin-block: 0 1.2em; }
:where(.ui-prose) :not(pre) > code, .ui-code { font-family: var(--mono); font-size: .88em; background: var(--tint); border: 1px solid var(--line); border-radius: var(--radius-xs); padding: .08em .35em; }
:where(.ui-prose) pre code { font-size: inherit; background: none; border: 0; padding: 0; }
/* the terminal quote: dark in both themes, because it quotes a terminal rather than being the page */
.ui-term { font-family: var(--mono); font-size: 13px; line-height: 1.6; background: var(--term-bg); color: var(--term-ink); border: 1px solid var(--line); border-radius: var(--radius-s); padding: 12px 16px; overflow-x: auto; white-space: pre-wrap; margin-block: 0 1.2em; }
.ui-term .p, .ui-term .c { color: var(--term-dim); }

/* tables: a glass sheet with a mono header row; wrap a wide one in .ui-scroll */
:where(.ui-prose) table, .ui-table { width: 100%; border-collapse: collapse; font-size: 15px; background: var(--surface-hi); border-radius: var(--radius-s); box-shadow: 0 0 0 1px var(--line); overflow: hidden; margin-block: 1em 1.4em; }
:is(:where(.ui-prose) table, .ui-table) :is(th, td) { padding: 9px 12px; text-align: left; border-bottom: 1px solid var(--line); vertical-align: top; }
:is(:where(.ui-prose) table, .ui-table) th { font-family: var(--mono); font-size: 11.5px; letter-spacing: .06em; text-transform: uppercase; color: var(--faint); font-weight: 500; background: var(--tint); }
:is(:where(.ui-prose) table, .ui-table) tr:last-child td { border-bottom: 0; }
:is(:where(.ui-prose) table, .ui-table) td.num, :is(:where(.ui-prose) table, .ui-table) th.num { text-align: right; }
.ui-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain; margin-block: 1em 1.4em; }
.ui-scroll > table { margin: 0; }

/* figures: a glass frame and a caption */
.ui-figure { margin-block: 1.4em 1.6em; padding: 18px 18px 12px; background: var(--surface-solid); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow); }
.ui-figure figcaption { margin-top: 10px; font-size: 13.5px; color: var(--muted); line-height: 1.5; }
.ui-figure svg text { font-family: var(--sans); }
@media (max-width: 640px) { :where(.ui-prose) :not(pre) > code { overflow-wrap: anywhere; } :where(.ui-prose) :is(p, li) { overflow-wrap: break-word; } }

/* ui-note: a message with a meaning. --ok (done), --wait (waiting on you / pending), --bad (wrong). Without a modifier it
   is a neutral aside. The meaning is carried twice: the colour of the rule and the word the note starts with.
     <p class="ui-note ui-note--wait" role="status"><strong>Waiting:</strong> the dealer has not replied.</p> */
.ui-note { --tone: var(--rule); margin-block: 0 1.1em; padding: 12px 16px; border-radius: var(--radius-s); border: 1px solid color-mix(in oklab, var(--tone) 30%, transparent); border-left: 3px solid var(--tone);
  background: color-mix(in oklab, var(--tone) 7%, var(--surface-solid)); color: var(--text); font-size: 15px; }
.ui-note > :last-child { margin-bottom: 0; }
.ui-note strong:first-child { color: var(--tone); }
.ui-note--ok { --tone: var(--ok); }
.ui-note--wait { --tone: var(--wait); }
.ui-note--bad { --tone: var(--bad); }
.ui-note--info { --tone: var(--accent); }
/* inline status text */
.ui-ok { color: var(--ok); } .ui-wait { color: var(--wait); } .ui-bad { color: var(--bad); } .ui-muted { color: var(--muted); } .ui-faint { color: var(--faint); }

/* ui-kv: facts two columns at a time, the key in mono, its value beside it; stacks on a phone.
     <dl class="ui-kv"><dt>version</dt><dd>3.0</dd><dt>network</dt><dd>Sepolia</dd></dl> */
.ui-kv { display: grid; grid-template-columns: minmax(8ch, max-content) 1fr; gap: 0 20px; margin-block: 0 1.2em; font-size: 15px; }
.ui-kv dt, .ui-kv dd { margin: 0; padding: 9px 0; border-bottom: 1px solid var(--line); }
.ui-kv dt { font-family: var(--mono); font-size: 13px; color: var(--accent); font-weight: 500; white-space: nowrap; }
.ui-kv dd { color: var(--muted); min-width: 0; overflow-wrap: anywhere; }
.ui-kv dt:last-of-type, .ui-kv dd:last-of-type { border-bottom: 0; }
@media (max-width: 560px) { .ui-kv { grid-template-columns: 1fr; } .ui-kv dt { border-bottom: 0; padding-bottom: 0; } }

/* ui-disclosure: a question and its answer, a hairline between rows, a + that turns. Native <details>, no script.
     <details class="ui-disclosure"><summary>Is it free?</summary><p>…</p></details> */
.ui-disclosure { border-bottom: 1px solid var(--line); }
.ui-disclosure > summary { list-style: none; cursor: pointer; display: flex; justify-content: space-between; align-items: baseline; gap: 16px; padding: 14px 0; font-weight: 600; color: var(--text-strong); }
.ui-disclosure > summary::-webkit-details-marker { display: none; }
.ui-disclosure > summary::after { content: "+"; font-family: var(--mono); font-weight: 400; color: var(--faint); transition: transform var(--t-fast) var(--ease-out); }
.ui-disclosure[open] > summary::after { transform: rotate(45deg); }
.ui-disclosure > :not(summary) { margin: 0 0 14px; color: var(--muted); }

/* ui-field: a label over its control. Inputs, selects and textareas take one look wherever they sit inside .ui-form (or
   carry .ui-input themselves). Focus is the accent ring.
     <form class="ui-form"><label class="ui-field">Email <input type="email"></label><button class="ui-btn ui-btn--primary">Send</button></form> */
.ui-form { display: grid; gap: 14px; max-width: 34rem; }
.ui-field { display: grid; gap: 6px; font-size: 14px; color: var(--muted); }
.ui-input, .ui-form :is(input:not([type="checkbox"], [type="radio"], [type="range"], [type="color"], [type="file"]), select, textarea) {
  font: inherit; font-size: 15px; color: var(--text); background: var(--surface-solid); border: 1px solid var(--line-2); border-radius: var(--radius-s); padding: 9px 12px; width: 100%;
  transition: border-color var(--t-fast) var(--ease-out), box-shadow var(--t-fast) var(--ease-out);
}
:is(.ui-input, .ui-form :is(input, select, textarea)):focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in oklab, var(--accent) 18%, transparent); }
:is(.ui-input, .ui-form :is(input, select, textarea))[aria-invalid="true"] { border-color: var(--bad); }
.ui-form textarea { min-height: 7em; resize: vertical; }
.ui-hint { font-size: 13px; color: var(--faint); }
.ui-form :is(input[type="checkbox"], input[type="radio"]) { accent-color: var(--accent); }

/* ui-foot: the page's last line. A row of links, then the legal line; a theme toggle may sit in it.
     <footer class="ui-foot ui-wrap"><nav aria-label="More"><a href="…">…</a></nav><p>Secure Data Research, LLC · Thousand Oaks, California</p></footer>
   The toggle: <button class="ui-theme" data-ui-theme type="button">theme: auto</button> (transitions.js wires it). */
.ui-foot { padding-block: 28px 40px; margin-top: clamp(40px, 6vw, 72px); border-top: 1px solid var(--line-2); font-size: 14px; color: var(--faint); }
.ui-foot nav { display: flex; flex-wrap: wrap; gap: 6px 20px; margin-bottom: 8px; }
.ui-foot a { color: var(--muted); text-decoration: none; }
.ui-foot a:hover { color: var(--text-strong); text-decoration: underline; }
.ui-foot p { margin: 0; }
.ui-theme { font: inherit; color: var(--muted); background: none; border: 0; padding: 0; cursor: pointer; }
.ui-theme:hover { color: var(--text-strong); }

}