/* sdr-ui 0.10.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 (README, "Motion"). Every transition and animation spends one curve and one duration from here; nothing else
     in the bundle writes a curve or a time (tools/check.ts, rule 7), so everything on a page moves the same way.
       curves     what arrives eases out; what leaves eases in; what changes in place, or two things trading places
                  (a cross-fade), eases both ways
       durations  a response to the pointer is fast; something arriving is medium; something leaving is quicker than it
                  arrived; a whole page changing sits between; a reveal is slow */
  --ease-out: cubic-bezier(.2, .8, .2, 1);
  --ease-in: cubic-bezier(.4, 0, 1, 1);
  --ease-both: cubic-bezier(.4, 0, .2, 1);
  --t-fast: 160ms;
  --t-in: 240ms;
  --t-out: 90ms;
  --t-page: 200ms;
  --t-slow: 450ms;
  /* the banner's drift: a long, even breath */
  --ease-drift: cubic-bezier(.45, 0, .55, 1);
  --t-drift: 48s;
}

/* 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 (boot.js / transitions.js). The old page and the new one overlap: neither fades to nothing before the other
   appears, because a moment with no page on screen reads as a flash, most of all between two dense pages. With
   cross-document view transitions the two cross-fade over --t-page; plus-lighter keeps whatever they share (the ground,
   content that did not change) at full strength throughout, so only what differs is seen to change. The top bar and the
   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: isolate; }
::view-transition-old(root) { mix-blend-mode: plus-lighter; animation: ui-page-out var(--t-page) var(--ease-both) both; }
::view-transition-new(root) { mix-blend-mode: plus-lighter; animation: ui-page-in var(--t-page) var(--ease-both) 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; } }
/* the same change where cross-document view transitions are missing (boot.js sets html.ui-nvt): a link is followed at
   once and the browser holds the old page on screen until the new one paints, so there is nothing to fade out. The new
   page settles in from nearly opaque, and only when a same-site link led to it (html.ui-arriving, from the flag
   transitions.js leaves). Never on a first visit, so the first paint is the page. */
html.ui-nvt.ui-arriving .ui-page { animation: ui-page-settle var(--t-in) var(--ease-out) both; }
@keyframes ui-page-settle { from { opacity: .86; } }

/* 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 var(--t-drift) 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); }

}