/* One design system for every page on this site.
 *
 * There were two. The front page was rebuilt and the explore page was not, so
 * the site had a different palette, typeface scale, header and button style
 * depending on which link you followed. Shared files rather than shared
 * discipline: the only way two pages stay identical is if there is one copy.
 *
 * Phone first in the places it matters. The desktop layout was designed at
 * 1180px and the phone got whatever fell out of it, which is backwards for a
 * page whose main job is search.
 */

/* Brand palette, section 26 of the brief. Nine colours, and nothing else is
   invented alongside them.

   Two honest notes about where values come from:
   
   --blue-light is sampled from the logo itself (the third stratum of the mark
   reads #5A8ACC), not made up to fill a gap. It is used only where the mark's
   own layering is being echoed.
   
   The brief specifies no dark palette. Rather than invent nine more hues, the
   dark theme is derived from the nine by mixing them against Ink and White
   with color-mix, so every dark value is traceable to a brand colour. The
   accent is lightened because Record Blue on Ink is about 3.4:1, under the
   4.5 the brief's own accessibility section asks for. */
:root{
  --bg:#FFFFFF;          /* White  */
  --alt:#F8FAFC;         /* Paper  */
  --panel:#FFFFFF;       /* White  */
  --ink:#111827;         /* Ink    */
  --ink2:#475569;        /* Slate  */
  --line:#E2E8F0;        /* Mist   */
  --accent:#2563EB;      /* Record Blue */
  --blue-light:#5A8ACC;  /* sampled from the mark */
  --added:#15803D;
  --changed:#B45309;
  --removed:#B91C1C;
  --accent-soft:color-mix(in srgb, var(--accent) 16%, transparent);
  --hover:#F8FAFC;
  --headerbg:color-mix(in srgb, #FFFFFF 90%, transparent);
  --good:var(--added);
  /* Bands that are meant to be dark stay dark in both themes. Without these
     they invert with --ink and --bg, which flipped the closing band white in
     dark mode and left its blue label invisible on it. */
  --inverse-bg:#111827;
  --inverse-fg:#F8FAFC;
  --inverse-accent:#5A8ACC;
  --sans:"Inter",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  --mono:"IBM Plex Mono",ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  --page:1180px; --gutter:20px; --ease:cubic-bezier(.16,1,.3,1);
}
@media(min-width:700px){ :root{ --gutter:24px; } }

/* Dark, derived. Every value is one of the nine mixed with Ink or White. */
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    --bg:#111827;
    --alt:color-mix(in srgb, #111827 88%, #FFFFFF);
    --panel:color-mix(in srgb, #111827 92%, #FFFFFF);
    --ink:#F8FAFC;
    --ink2:color-mix(in srgb, #E2E8F0 72%, #111827);
    --line:color-mix(in srgb, #E2E8F0 22%, #111827);
    --accent:color-mix(in srgb, #2563EB 55%, #FFFFFF);
    --blue-light:color-mix(in srgb, #5A8ACC 70%, #FFFFFF);
    --added:color-mix(in srgb, #15803D 45%, #FFFFFF);
    --changed:color-mix(in srgb, #B45309 55%, #FFFFFF);
    --removed:color-mix(in srgb, #B91C1C 50%, #FFFFFF);
    --hover:color-mix(in srgb, #111827 86%, #FFFFFF);
    --headerbg:color-mix(in srgb, #111827 90%, transparent);
  }
}
:root[data-theme="dark"]{
  --bg:#111827;
  --alt:color-mix(in srgb, #111827 88%, #FFFFFF);
  --panel:color-mix(in srgb, #111827 92%, #FFFFFF);
  --ink:#F8FAFC;
  --ink2:color-mix(in srgb, #E2E8F0 72%, #111827);
  --line:color-mix(in srgb, #E2E8F0 22%, #111827);
  --accent:color-mix(in srgb, #2563EB 55%, #FFFFFF);
  --blue-light:color-mix(in srgb, #5A8ACC 70%, #FFFFFF);
  --added:color-mix(in srgb, #15803D 45%, #FFFFFF);
  --changed:color-mix(in srgb, #B45309 55%, #FFFFFF);
  --removed:color-mix(in srgb, #B91C1C 50%, #FFFFFF);
  --hover:color-mix(in srgb, #111827 86%, #FFFFFF);
  --headerbg:color-mix(in srgb, #111827 90%, transparent);
}

*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
body{margin:0;background:var(--bg);color:var(--ink);font:400 17px/1.6 var(--sans);
  font-feature-settings:"tnum" 1;-webkit-font-smoothing:antialiased;
  /* Nothing on this site is meant to scroll sideways. If something does, it is
     a bug in that component and it should not take the page with it. */
  overflow-x:hidden}
a{color:var(--accent);text-decoration:none}
a:hover{text-decoration:underline}
h1,h2,h3{margin:0;font-weight:600;letter-spacing:-.032em;line-height:1.08;
  overflow-wrap:break-word}
h1{font-size:clamp(30px,7.2vw,62px)}
h2{font-size:clamp(22px,4.6vw,34px);letter-spacing:-.028em}
h3{font-size:16px;letter-spacing:-.012em;line-height:1.3}
p{margin:0}
.wrap{max-width:var(--page);margin:0 auto;padding:0 var(--gutter)}
.lede{font-size:clamp(16px,4vw,20px);line-height:1.55;color:var(--ink2);max-width:62ch}
.muted{color:var(--ink2)}
.small{font-size:13px}
.mono{font-family:var(--mono);font-size:13px;overflow-wrap:anywhere}

/* el.hidden has to win. The UA rule that implements it is [hidden]{display:none},
   and a UA declaration loses to any author one, so .shelves{display:grid} and
   .more{display:block} quietly kept both visible however often the script set
   hidden. That is why a portal search drew its results below the browse
   shelves rather than in place of them. */
[hidden]{display:none !important}

/* Motion reveals. It never decorates and never gates readability. */
.r{opacity:0;transform:translateY(18px);transition:opacity .7s var(--ease),transform .7s var(--ease)}
.r.in{opacity:1;transform:none}
@media (prefers-reduced-motion:reduce){
  .r{opacity:1;transform:none;transition:none}
  html{scroll-behavior:auto}
}

/* Header */
header{position:sticky;top:0;z-index:40;background:var(--headerbg);
  backdrop-filter:saturate(180%) blur(20px);border-bottom:1px solid transparent;
  transition:border-color .3s}
header.stuck{border-bottom-color:var(--line)}
header .wrap{display:flex;align-items:center;gap:16px;height:58px}
@media(min-width:700px){ header .wrap{height:64px;gap:24px} }
.brand{font-size:18px;font-weight:600;letter-spacing:-.028em;color:var(--ink);
  white-space:nowrap}
.brand:hover{text-decoration:none}
/* Scoped to the header on purpose. As a bare element selector this pushed
   every nav on the site to the right of its container, which is why both
   footer columns sat hard against the right edge of their grid cells. */
header nav{margin-left:auto;display:flex;gap:18px;align-items:center}
header nav a{color:var(--ink);font-size:14px;white-space:nowrap}
.hcount{font-size:13px;color:var(--ink2);font-variant-numeric:tabular-nums}
@media(max-width:760px){nav a.hide,.hcount{display:none}}

/* Hero and search */
.hero{padding:clamp(30px,7vh,104px) 0 clamp(22px,4vh,44px)}
.hero h1{max-width:17ch}
.hero .lede{margin-top:16px}
@media(min-width:700px){ .hero .lede{margin-top:20px} }
.searchbar{margin-top:24px;position:relative;max-width:720px}
@media(min-width:700px){ .searchbar{margin-top:34px} }
.searchbar input{width:100%;font:400 17px/1.4 var(--sans);color:var(--ink);
  padding:15px 16px 15px 46px;border:1px solid var(--line);background:var(--bg);
  border-radius:0;outline:none;transition:border-color .2s,box-shadow .2s;
  -webkit-appearance:none}
@media(min-width:700px){
  .searchbar input{font-size:19px;padding:18px 20px 18px 52px}
}
.searchbar input:focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
.searchbar svg{position:absolute;left:16px;top:50%;transform:translateY(-50%);
  width:18px;height:18px;stroke:var(--ink2);fill:none;stroke-width:2}
@media(min-width:700px){ .searchbar svg{left:19px} }
.searchmeta{margin-top:10px;font-size:13px;color:var(--ink2);min-height:20px}

/* Figures */
.figs{display:grid;gap:1px;background:var(--line);border:1px solid var(--line);
  grid-template-columns:repeat(2,1fr);margin-top:28px}
@media(min-width:860px){ .figs{grid-template-columns:repeat(4,1fr);margin-top:40px} }
.fig{background:var(--bg);padding:16px 14px}
@media(min-width:700px){ .fig{padding:22px 20px} }
.fig .n{font-size:clamp(21px,5.4vw,32px);font-weight:600;letter-spacing:-.03em;
  font-variant-numeric:tabular-nums;line-height:1.1}
.fig .k{font-size:11.5px;color:var(--ink2);margin-top:4px;letter-spacing:.01em}

/* Chips. On a phone these become one scrolling strip rather than four stacked
   rows of buttons pushing the content below the fold. */
.chipwrap{margin:26px 0 0}
.chips{display:flex;gap:8px;overflow-x:auto;scrollbar-width:none;
  padding-bottom:4px;-webkit-overflow-scrolling:touch}
.chips::-webkit-scrollbar{display:none}
@media(min-width:900px){ .chips{flex-wrap:wrap;overflow:visible} }
.chip{font:500 13px/1 var(--sans);padding:11px 14px;border:1px solid var(--line);
  background:var(--bg);color:var(--ink);cursor:pointer;transition:.15s;
  white-space:nowrap;flex:0 0 auto}
.chip:hover{border-color:var(--ink2)}
.chip[aria-pressed="true"]{background:var(--ink);color:var(--bg);border-color:var(--ink)}

/* Sections and cards */
section{padding:clamp(34px,6vh,76px) 0}
.tint{background:var(--alt)}
.shead{display:flex;align-items:baseline;gap:6px 16px;margin-bottom:8px;flex-wrap:wrap}
.shead p{color:var(--ink2);font-size:14px}
@media(min-width:700px){ .shead p{font-size:15px} }
.grid{display:grid;gap:1px;background:var(--line);border:1px solid var(--line);
  grid-template-columns:1fr;margin-top:20px}
@media(min-width:640px){ .grid{grid-template-columns:repeat(2,1fr);margin-top:26px} }
@media(min-width:980px){ .grid{grid-template-columns:repeat(3,1fr)} }
.card{background:var(--bg);padding:16px;display:flex;gap:13px;text-align:left;
  border:0;font:inherit;color:inherit;cursor:pointer;align-items:flex-start;
  transition:background .15s;width:100%;min-width:0}
@media(min-width:700px){ .card{padding:20px;gap:14px} }
.card:hover{background:var(--hover)}
.mono-tile{flex:0 0 38px;height:38px;display:grid;place-items:center;
  background:var(--alt);color:var(--ink2);font:600 13px/1 var(--sans);
  letter-spacing:-.02em;text-transform:uppercase}
.card .body{min-width:0;flex:1}
.card h3{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.card .sub{font-size:12px;color:var(--ink2);margin-top:2px;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.card .desc{font-size:14px;line-height:1.45;color:var(--ink2);margin-top:8px;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.tags{display:flex;gap:6px;flex-wrap:wrap;margin-top:11px;align-items:center}
.tag{font:500 11px/1 var(--sans);padding:5px 8px;border:1px solid var(--line);
  color:var(--ink2);letter-spacing:.02em;white-space:nowrap}
.tag.ok{border-color:color-mix(in srgb,var(--added) 35%,transparent);color:var(--added)}
/* What happened to a record, never a judgement about it. */
.tag.added{border-color:color-mix(in srgb,var(--added) 35%,transparent);color:var(--added)}
.tag.changed{border-color:color-mix(in srgb,var(--changed) 40%,transparent);color:var(--changed)}
.tag.removed{border-color:color-mix(in srgb,var(--removed) 40%,transparent);color:var(--removed)}
/* Status is never carried by colour alone: each chip keeps its word. */
.hash{font-family:var(--mono);font-size:12.5px;overflow-wrap:anywhere;color:var(--ink)}
.metric{font:600 12px/1 var(--sans);color:var(--ink);
  font-variant-numeric:tabular-nums;white-space:nowrap}
@media(min-width:520px){ .metric{margin-left:auto} }
.metric span{font-weight:400;color:var(--ink2)}

/* Result and browse rows. Two lines on a phone, one on a desktop: the same
   information either way, never a sideways scroll. */
.rows{border:1px solid var(--line);margin-top:18px}
.row{display:flex;gap:12px;align-items:flex-start;padding:12px 14px;
  border-bottom:1px solid var(--line);background:var(--bg);width:100%;
  text-align:left;border-left:0;border-right:0;border-top:0;font:inherit;
  color:inherit;cursor:pointer;min-width:0}
@media(min-width:700px){
  .row{align-items:center;padding:13px 18px;gap:14px}
}
.row:last-child{border-bottom:0}
.row:hover{background:var(--hover)}
.row .main{min-width:0;flex:1;display:flex;flex-direction:column;gap:3px}
@media(min-width:700px){
  .row .main{flex-direction:row;align-items:center;gap:14px}
}
.row .nm{font-weight:500;font-size:15px;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap;min-width:0;flex:1}
.row .meta{display:flex;gap:12px;align-items:center;flex-wrap:wrap}
.row .vs{font-family:var(--mono);font-size:12px;color:var(--ink2);white-space:nowrap}
/* Least useful first out on a narrow screen. */
@media(max-width:520px){ .row .vs.drop{display:none} }

/* Detail panel */
.scrim{position:fixed;inset:0;background:rgba(0,0,0,.28);opacity:0;
  pointer-events:none;transition:opacity .3s var(--ease);z-index:50}
.scrim.open{opacity:1;pointer-events:auto}
.panel{position:fixed;top:0;right:0;bottom:0;width:min(680px,100%);background:var(--bg);
  z-index:51;transform:translateX(100%);transition:transform .4s var(--ease);
  overflow-y:auto;-webkit-overflow-scrolling:touch;box-shadow:-1px 0 0 var(--line)}
.panel.open{transform:none}
.panel .inner{position:relative;padding:20px 20px 60px}
@media(min-width:700px){ .panel .inner{padding:26px 64px 60px 30px} }
.panel .close{position:absolute;top:12px;right:12px;background:var(--panel);
  border:1px solid var(--line);font:400 20px/1 var(--sans);color:var(--ink2);
  cursor:pointer;width:40px;height:40px;display:grid;place-items:center}
@media(min-width:700px){ .panel .close{top:18px;right:22px;border-color:transparent;font-size:26px} }
.panel .close:hover{color:var(--ink);border-color:var(--line)}
.panel h2{font-size:21px;overflow-wrap:anywhere;padding-right:48px}
@media(min-width:700px){ .panel h2{font-size:26px;padding-right:0} }
.kv{display:grid;grid-template-columns:1fr;gap:2px 18px;margin-top:18px;font-size:14px}
@media(min-width:520px){ .kv{grid-template-columns:auto 1fr;gap:6px 18px} }
.kv dt{color:var(--ink2)}
.kv dd{margin:0 0 8px;overflow-wrap:anywhere}
@media(min-width:520px){ .kv dd{margin-bottom:0} }

/* Tables are the one thing allowed to scroll sideways, inside their own box. */
.scroller{overflow-x:auto;-webkit-overflow-scrolling:touch;margin-top:14px}
.vtable{width:100%;border-collapse:collapse;font-size:14px;min-width:340px}
.vtable th{text-align:left;font-weight:500;color:var(--ink2);font-size:11px;
  letter-spacing:.03em;text-transform:uppercase;padding:0 12px 8px 0;
  border-bottom:1px solid var(--line);white-space:nowrap}
.vtable td{padding:10px 12px 10px 0;border-bottom:1px solid var(--line);
  vertical-align:top}
.vtable td.v{font-family:var(--mono);font-size:12.5px;overflow-wrap:anywhere}
.dot{display:inline-block;width:7px;height:7px;background:var(--good);
  margin-right:7px;vertical-align:middle}
.dot.off{background:var(--line)}

.more{display:block;width:100%;padding:14px;margin:20px 0 0;border:1px solid var(--line);
  background:var(--bg);color:var(--ink2);font:inherit;font-size:14px;cursor:pointer}
.more:hover{border-color:var(--accent);color:var(--accent)}


.spinner{display:inline-block;width:13px;height:13px;border:2px solid var(--line);
  border-top-color:var(--accent);border-radius:50%;animation:spin .7s linear infinite;
  vertical-align:-2px}
@keyframes spin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){.spinner{animation:none}}


/* Keyboard focus must be visible. Every interactive thing here is a button or
   an input, and several are borderless by design, so the ring has to come from
   the token set rather than the browser default that the reset removes. */
:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:2px}
.card:focus-visible,.row:focus-visible,.chip:focus-visible{outline-offset:-2px}

/* The metric tiles are baked with real values at deploy time and refreshed by
   script, so reserve the line box either way and the number never reflows. */
.fig .n{min-height:1.1em}

/* Server record header: label and value, stacked on a phone. */
.facts{display:grid;grid-template-columns:1fr;gap:2px 20px;margin-top:20px;font-size:14px}
@media(min-width:520px){ .facts{grid-template-columns:auto 1fr;gap:8px 20px} }
.facts dt{color:var(--ink2);white-space:nowrap}
.facts dd{margin:0 0 10px;font-variant-numeric:tabular-nums}
@media(min-width:520px){ .facts dd{margin-bottom:0} }
.vtable td .hash{font-size:12px}


/* ============================================================
   The register.

   This site is a record, so it is set like one: ruled, columnar, and labelled
   in mono the way an index or a specimen sheet is. The earlier version was a
   white SaaS landing page with a table bolted on, which described the product
   without looking like it.

   Three rules hold it together.
   1. Hairlines, not boxes. Structure comes from rules and alignment; a border
      on four sides says "card" and cards say "marketing".
   2. Mono carries the metadata. Every label, date, figure and hash is IBM Plex
      Mono. Inter is for prose and the claim, nothing else.
   3. The data is the imagery. No illustration. A real record, with real dates
      and a real hash, is more convincing than any diagram of one.
   ============================================================ */

.bar{display:flex;align-items:center;gap:20px;height:60px}
/* Sized against the artwork, not the canvas it used to ship on. The brand
   file carries 41% vertical padding, so height:24px there drew a 14px
   wordmark sitting high in its own box, which is why it could not be read. */
.brand img{display:block;height:30px;width:auto}
.brand:hover{text-decoration:none}

/* The mark is three stacked strata. Section breaks echo it. */
.strata{height:5px;display:flex;flex-direction:column;gap:1px}
.strata i{display:block;height:1px;background:var(--ink)}
.strata i:nth-child(2){background:var(--accent)}
.strata i:nth-child(3){background:var(--blue-light)}

/* The thumb bar is a phone affordance and every rule that makes it one lives
   in the max-width:899px block. Above that it had no rules at all, so it was
   not absent, it was an unstyled div: a stray "Open the portal" button sitting
   below the footer on every desktop visit. It is off by default and the phone
   layout turns it on. Declared here, before that block, so the media rule is
   the later of two equal selectors and still wins. */
.actionbar{display:none}

.btn{display:inline-flex;align-items:center;justify-content:center;
  background:var(--ink);color:var(--bg);border:1px solid var(--ink);
  padding:10px 18px;font:500 13px/1 var(--mono);letter-spacing:.04em;
  white-space:nowrap;transition:background .15s,color .15s}
.btn:hover{background:var(--accent);border-color:var(--accent);color:var(--bg);text-decoration:none}
.btn.ghost{background:transparent;color:var(--ink)}
.btn.ghost:hover{background:transparent;color:var(--accent);border-color:var(--accent)}
.btn.lg{padding:14px 22px;font-size:13.5px}

/* ---------- the company page ---------- */
.marketing{background:var(--bg)}
.marketing header{border-bottom:1px solid var(--ink)}
.marketing header nav{display:flex;align-items:center;gap:22px;margin-left:auto}
.marketing header nav a{font:500 12.5px/1 var(--mono);letter-spacing:.05em;color:var(--ink)}
.marketing header nav a.btn{color:var(--bg)}
.marketing header nav a.btn:hover{color:#fff}

/* Every band is a ruled row: a mono label in the margin, content beside it. */
.band{border-bottom:1px solid var(--line);padding:clamp(40px,6vh,72px) 0}
.band > .wrap{display:grid;gap:14px 40px}
@media(min-width:900px){
  .band > .wrap{grid-template-columns:172px minmax(0,1fr)}
}
.band-label{font:500 11px/1.5 var(--mono);letter-spacing:.12em;text-transform:uppercase;
  color:var(--ink2)}
@media(min-width:900px){ .band-label{position:sticky;top:86px} }
.band-body{min-width:0}

.marketing h1{font:700 clamp(38px,6.8vw,74px)/0.97 var(--sans);letter-spacing:-.042em;
  text-wrap:balance;max-width:13ch;margin:0}
.marketing h2{font:600 clamp(22px,2.9vw,31px)/1.15 var(--sans);letter-spacing:-.025em;
  text-wrap:balance;max-width:26ch;margin:0 0 20px}
.marketing h3{font:600 15.5px/1.3 var(--sans);letter-spacing:-.008em;margin:0}
.marketing p{font-size:16px;line-height:1.65;color:var(--ink2)}
.marketing .lede{font-size:clamp(16px,1.6vw,18.5px);line-height:1.6;color:var(--ink2);
  max-width:62ch;margin:0}

.eyebrow{font:500 11px/1 var(--mono);letter-spacing:.16em;text-transform:uppercase;
  color:var(--accent);margin:0 0 22px}
.hero-band .lede{margin-top:26px}
.cta-row{display:flex;gap:10px;flex-wrap:wrap;margin-top:32px}

/* Three questions, as ruled entries rather than cards with accent bars. */
.cols3{display:grid;gap:0;border-top:1px solid var(--line)}
@media(min-width:820px){ .cols3{grid-template-columns:repeat(3,1fr);gap:0 36px} }
.cols3 article{padding:20px 0;border-bottom:1px solid var(--line)}
@media(min-width:820px){ .cols3 article{border-bottom:0;padding:20px 0 0} }
.cols3 p{margin-top:9px;font-size:15px;line-height:1.6}

/* The specimen: a real record, set the way the portal sets one. */
.specimen{border:1px solid var(--ink);margin-top:4px;background:var(--bg)}
.specimen .sp-head{display:flex;align-items:baseline;justify-content:space-between;
  gap:12px;flex-wrap:wrap;padding:12px 16px;border-bottom:1px solid var(--ink);
  background:var(--inverse-bg)}
.specimen .sp-head b{font:500 13px/1.3 var(--mono);color:var(--inverse-fg);overflow-wrap:anywhere}
.specimen .sp-head span{font:400 10.5px/1 var(--mono);letter-spacing:.1em;
  text-transform:uppercase;color:var(--inverse-accent)}
.sp-rows{display:grid}
.sp-rows div{display:grid;grid-template-columns:minmax(96px,auto) minmax(0,1fr);
  gap:8px 18px;padding:9px 16px;border-bottom:1px solid var(--line);font-size:13.5px}
.sp-rows div:last-child{border-bottom:0}
.sp-rows dt{font:400 11px/1.5 var(--mono);letter-spacing:.07em;text-transform:uppercase;
  color:var(--ink2)}
.sp-rows dd{margin:0;font-family:var(--mono);font-size:12.5px;overflow-wrap:anywhere;
  color:var(--ink)}
.sp-note{font:400 11.5px/1.5 var(--mono);color:var(--ink2);padding:10px 16px;
  background:var(--alt);border-top:1px solid var(--line)}

/* Two observations of one version, as a diff rather than two cards. */
.evidence-pair{margin-top:4px;border:1px solid var(--line)}
.obs-card{margin:0;display:grid;grid-template-columns:minmax(0,1fr);gap:4px;
  padding:14px 16px;border-bottom:1px solid var(--line)}
@media(min-width:620px){
  .obs-card{grid-template-columns:150px 78px minmax(0,1fr);align-items:baseline;gap:16px}
}
.obs-card:last-child{border-bottom:0}
.obs-card.flagged{background:color-mix(in srgb,var(--changed) 7%,transparent);
  box-shadow:inset 3px 0 0 var(--changed)}
.obs-card figcaption{font:400 11px/1.4 var(--mono);letter-spacing:.07em;
  text-transform:uppercase;color:var(--ink2)}
.obs-card b{font:500 14px/1 var(--mono);color:var(--ink)}
.obs-card .hash{font-family:var(--mono);font-size:12.5px;color:var(--ink);overflow-wrap:anywhere}
.between{display:none}
.footnote{margin-top:18px;font-size:14.5px;line-height:1.6;color:var(--ink2);max-width:74ch}
.footnote strong{color:var(--ink);font-weight:600}

/* The sequence is genuinely a sequence, so it is numbered. */
.pipeline{list-style:none;counter-reset:step;margin:0;padding:0;
  border-top:1px solid var(--line)}
.pipeline li{counter-increment:step;display:grid;
  grid-template-columns:34px minmax(0,1fr);gap:4px 14px;padding:13px 0;
  border-bottom:1px solid var(--line);align-items:baseline}
@media(min-width:700px){
  .pipeline li{grid-template-columns:34px 190px minmax(0,1fr);gap:16px}
}
.pipeline li::before{content:counter(step,decimal-leading-zero);
  font:500 11px/1.5 var(--mono);color:var(--accent);letter-spacing:.06em}
.pipeline b{font:600 14.5px/1.4 var(--sans);letter-spacing:-.005em}
.pipeline span{font-size:14px;line-height:1.55;color:var(--ink2);grid-column:2/-1}
@media(min-width:700px){ .pipeline span{grid-column:3/-1} }

.sources-row{margin-top:26px}
.src-label{font:500 11px/1 var(--mono);letter-spacing:.1em;text-transform:uppercase;
  color:var(--ink2);margin:0 0 12px}
.src-list{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:0 22px}
.src-list li{font:400 13px/2 var(--mono);color:var(--ink);position:relative;padding-left:14px}
.src-list li::before{content:"";position:absolute;left:0;top:calc(1em - 1px);
  width:7px;height:1px;background:var(--accent)}

.limits{list-style:none;margin:0;padding:0;border-top:1px solid var(--line)}
.limits li{padding:13px 0 13px 26px;border-bottom:1px solid var(--line);position:relative;
  font-size:15px;line-height:1.6;color:var(--ink2)}
.limits li::before{content:"\2014";position:absolute;left:0;color:var(--ink2);
  font-family:var(--mono);font-size:13px}
.cta-inline{margin-top:22px;font:500 13px/1 var(--mono);letter-spacing:.04em}

.closing{background:var(--inverse-bg);border-bottom:0}
.closing .band-label{color:var(--inverse-accent)}
.closing h2{color:var(--inverse-fg)}
.closing .lede{color:color-mix(in srgb, var(--inverse-fg) 78%, var(--inverse-bg))}
.closing .btn{background:var(--inverse-fg);color:var(--inverse-bg);border-color:var(--inverse-fg)}
.closing .btn:hover{background:var(--accent);border-color:var(--accent);color:#FFFFFF}
.closing .cta-row{margin-top:26px}

footer{background:var(--bg);border-top:1px solid var(--ink);padding:36px 0 48px;
  font-size:14px;color:var(--ink2)}
footer a{color:var(--ink2)}
footer a:hover{color:var(--accent)}
footer p+p{margin-top:8px}
.foot-grid{display:grid;gap:28px}
@media(min-width:760px){ .foot-grid{grid-template-columns:2fr 1fr 1fr;gap:40px} }
.foot-logo{height:32px;width:auto;display:block;margin-bottom:16px}
.foot-grid p{font-size:13.5px;color:var(--ink2);line-height:1.6}
.foot-grid .fine{font-size:12px;margin-top:10px}
.foot-grid nav{display:flex;flex-direction:column;gap:8px;align-items:flex-start;
  margin-left:0}
.col-head{font:500 10.5px/1 var(--mono);letter-spacing:.12em;text-transform:uppercase;
  color:var(--ink);margin-bottom:4px}
.foot-grid nav a{font:400 13px/1 var(--mono);color:var(--ink2)}

/* ---------- the portal ---------- */
.portal{background:var(--alt)}
.portal-bar{background:var(--bg);border-bottom:1px solid var(--ink)}
.portal-bar .bar{max-width:none;padding:0 18px;gap:16px}
.topsearch{flex:1;position:relative;max-width:640px;display:flex}
.topsearch input{width:100%;font:400 13.5px/1.4 var(--mono);color:var(--ink);
  padding:9px 12px 9px 34px;border:1px solid var(--line);background:var(--bg);
  outline:none;-webkit-appearance:none}
.topsearch input:focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
.topsearch svg{position:absolute;left:11px;top:50%;transform:translateY(-50%);
  width:15px;height:15px;stroke:var(--ink2);fill:none;stroke-width:2}
.portal-nav{display:flex;gap:16px;align-items:center}
.portal-nav a{font:500 12.5px/1 var(--mono);letter-spacing:.04em;color:var(--ink2)}
@media(max-width:700px){ .portal-nav{display:none} .brand img{height:25px} }

.console{display:grid;grid-template-columns:1fr;align-items:start}
@media(min-width:900px){ .console{grid-template-columns:238px minmax(0,1fr)} }
.facets{background:var(--bg);border-right:1px solid var(--line);
  padding:18px;display:flex;flex-direction:column;gap:20px}
@media(min-width:900px){ .facets{position:sticky;top:68px;height:calc(100svh - 68px);overflow-y:auto} }
.facet-head{display:flex;align-items:baseline;justify-content:space-between}
.facet-head h2{font:500 10.5px/1 var(--mono);letter-spacing:.12em;text-transform:uppercase;
  color:var(--ink)}
.linkish{background:none;border:0;color:var(--accent);font:500 12px/1 var(--mono);
  cursor:pointer;padding:2px}
.facet{border:0;margin:0;padding:0}
.facet legend{font:400 10.5px/1 var(--mono);letter-spacing:.1em;text-transform:uppercase;
  color:var(--ink2);margin-bottom:9px;padding:0}
.opts{display:flex;flex-direction:column}
.opt{display:flex;align-items:center;gap:9px;padding:6px 8px;margin:0 -8px;
  font-size:13.5px;cursor:pointer}
.opt:hover{background:var(--alt)}
.opt input{accent-color:var(--accent);margin:0}
.facet-note{font:400 11.5px/1.55 var(--mono);color:var(--ink2);
  border-top:1px solid var(--line);padding-top:14px}

.results{padding:18px;min-width:0}
@media(min-width:900px){ .results{padding:22px 26px 56px} }
.results-head{display:flex;align-items:baseline;justify-content:space-between;
  gap:16px;flex-wrap:wrap;margin-bottom:14px}
.results-head h1{font:500 14px/1 var(--mono);letter-spacing:.04em;color:var(--ink);
  font-variant-numeric:tabular-nums;text-transform:uppercase}
.sortwrap{display:flex;align-items:center;gap:8px;font:400 11.5px/1 var(--mono);
  letter-spacing:.06em;text-transform:uppercase;color:var(--ink2)}
.sortwrap select{font:400 12.5px/1 var(--mono);padding:7px 9px;border:1px solid var(--line);
  background:var(--bg);color:var(--ink);outline:none;text-transform:none;letter-spacing:0}
.sortwrap select:focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}

.tablewrap{background:var(--bg);border:1px solid var(--line);overflow-x:auto}
table.records{width:100%;border-collapse:collapse;font-size:13.5px}
table.records thead th{position:sticky;top:0;z-index:2;background:var(--bg);
  text-align:left;font:500 10.5px/1 var(--mono);letter-spacing:.1em;text-transform:uppercase;
  color:var(--ink2);padding:11px 14px;border-bottom:1px solid var(--ink);white-space:nowrap}
table.records td{padding:10px 14px;border-bottom:1px solid var(--line);vertical-align:middle}
table.records tbody tr{cursor:pointer}
table.records tbody tr:hover{background:var(--alt)}
table.records tbody tr:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
table.records tr:last-child td{border-bottom:0}
.records .nm{display:block;font-weight:500;letter-spacing:-.008em}
.records .id{display:block;font-family:var(--mono);font-size:11px;color:var(--ink2);
  margin-top:2px;overflow-wrap:anywhere}
.records .num{text-align:right;font-family:var(--mono);font-variant-numeric:tabular-nums;
  white-space:nowrap;font-size:12.5px}
.records .mono{font-family:var(--mono);font-size:12px;color:var(--ink2);white-space:nowrap}
.pill{display:inline-block;font:400 10.5px/1 var(--mono);border:1px solid var(--line);
  padding:4px 6px;margin:0 4px 0 0;color:var(--ink2);letter-spacing:.04em}
@media(max-width:820px){ .hide-sm{display:none} }
@media(max-width:560px){ .hide-xs{display:none} }

tr.empty td{padding:38px 20px;text-align:center}
tr.empty b{display:block;font-size:15px;margin-bottom:6px}
tr.empty span{display:block;color:var(--ink2);font-size:13.5px;max-width:46ch;margin:0 auto}
tr.skeleton td{padding:13px 14px}
tr.skeleton span{display:block;height:12px;background:var(--line);opacity:.55;
  animation:pulse 1.4s ease-in-out infinite}
@keyframes pulse{0%,100%{opacity:.35}50%{opacity:.7}}
@media (prefers-reduced-motion:reduce){ tr.skeleton span{animation:none} }
.dots::after{content:"…"}
.results-foot{margin-top:13px;font:400 11.5px/1 var(--mono);color:var(--ink2)}
.results .more{margin-top:14px;font-family:var(--mono);font-size:12.5px;letter-spacing:.04em}

/* Claim and specimen side by side once there is room for both; stacked below
   that, with the specimen after the call to action rather than between the
   claim and it. */
.hero-grid{display:grid;gap:34px}
.hero-claim{max-width:none}
.hero-band .lede{max-width:64ch}

/* ============================================================
   Mobile.

   Both surfaces were drawn at desktop and left to reflow, which on a phone
   gives you a squeezed website rather than something you want to hold. These
   rules treat the phone as its own layout: the portal becomes a list with a
   filter sheet, the record opens as a bottom sheet, and the company page gets
   a persistent action bar instead of a call to action you have to hunt for.

   Everything here is a max-width override so the desktop layout above stays
   exactly as it is.
   ============================================================ */

:root{
  --safe-b:env(safe-area-inset-bottom, 0px);
  --safe-t:env(safe-area-inset-top, 0px);
}

@media (max-width: 899px){
  /* Tap targets. Anything you press gets 44px of height whatever the type
     size says, which is the one rule a phone layout cannot negotiate. */
  .btn{min-height:46px;padding:12px 18px}
  .opt{min-height:44px;padding:10px 8px}
  nav a{min-height:36px;display:inline-flex;align-items:center}

  /* ---- company page ---- */
  .marketing header .bar{height:56px;gap:12px}
  .marketing header nav{gap:14px}
  .marketing header nav a:not(.btn){display:none}
  .marketing header nav a.btn{min-height:38px;padding:9px 14px;font-size:12px}

  .hero-band{padding:26px 0 24px}
  .marketing h1{font-size:clamp(31px,8.6vw,46px);line-height:1.0;max-width:none}
  .hero-band .lede{margin-top:16px;font-size:16px}
  .cta-row{margin-top:22px;display:grid;grid-template-columns:1fr;gap:10px}
  .cta-row .btn{width:100%}

  /* Figures read as a 2x2 card of numbers rather than four stacked lines. */

  .specimen{margin-top:26px}
  .sp-rows div{grid-template-columns:minmax(84px,auto) minmax(0,1fr);
    gap:6px 14px;padding:10px 14px;font-size:13px}

  .band{padding:30px 0}
  .band > .wrap{gap:12px}
  .band-label{font-size:10.5px;letter-spacing:.14em}
  .marketing h2{font-size:clamp(21px,5.6vw,26px);margin-bottom:14px;max-width:none}
  .cols3 article{padding:16px 0}
  .pipeline li{padding:12px 0;gap:3px 12px}
  .limits li{padding:12px 0 12px 22px;font-size:14.5px}
  .obs-card{padding:12px 14px}
  .footnote{font-size:14px}
  .foot-grid{gap:22px}

  /* An app keeps its primary action within thumb reach instead of at the
     bottom of the page. Appears once the hero has been scrolled past. */
  .actionbar{display:block;position:fixed;left:0;right:0;bottom:0;z-index:45;
    background:var(--headerbg);backdrop-filter:saturate(180%) blur(12px);
    border-top:1px solid var(--line);
    padding:10px 16px calc(10px + var(--safe-b));
    transform:translateY(120%);transition:transform .28s var(--ease)}
  .actionbar.up{transform:none}
  .actionbar .btn{width:100%}
  .marketing{padding-bottom:0}
  .marketing.has-bar footer{padding-bottom:calc(48px + 66px + var(--safe-b))}
}
@media (max-width: 899px) and (prefers-reduced-motion: reduce){
  .actionbar{transition:none}
}

/* ---- portal as an app ---- */
@media (max-width: 899px){
  .portal-bar .bar{height:54px;padding:0 14px;gap:10px}
  .portal-bar .brand img{height:24px}
  .topsearch input{font-size:16px;padding:11px 12px 11px 34px}  /* 16px: iOS
     zooms the whole page on focus for anything smaller */

  /* A toolbar that stays put: result count, filters, sort. */
  .toolbar{position:sticky;top:60px;z-index:30;display:flex;align-items:center;
    gap:10px;background:var(--bg);border-bottom:1px solid var(--line);
    padding:9px 14px}
  .toolbar .count{font:500 11.5px/1 var(--mono);letter-spacing:.06em;
    text-transform:uppercase;color:var(--ink2);flex:1;min-width:0;
    overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .filterbtn{display:inline-flex;align-items:center;gap:7px;min-height:38px;
    padding:8px 13px;border:1px solid var(--line);background:var(--bg);
    color:var(--ink);font:500 12px/1 var(--mono);letter-spacing:.04em;cursor:pointer}
  .filterbtn[aria-expanded="true"]{border-color:var(--accent);color:var(--accent)}
  .filterbtn .dot{width:6px;height:6px;background:var(--accent);display:none}
  .filterbtn.on .dot{display:block}
  .results-head{display:none}

  /* The filter panel becomes a sheet from the bottom. */
  .facets{position:fixed;left:0;right:0;bottom:0;z-index:60;
    height:auto;max-height:82svh;overflow-y:auto;border-right:0;
    border-top:1px solid var(--ink);padding:14px 16px calc(20px + var(--safe-b));
    transform:translateY(102%);transition:transform .3s var(--ease);
    box-shadow:0 -12px 32px rgba(17,24,39,.16)}
  .facets.open{transform:none}
  .facets::before{content:"";display:block;width:38px;height:4px;
    background:var(--line);margin:0 auto 14px}
  .sheet-scrim{position:fixed;inset:0;background:rgba(17,24,39,.4);z-index:55;
    opacity:0;pointer-events:none;transition:opacity .25s var(--ease)}
  .sheet-scrim.open{opacity:1;pointer-events:auto}
  .facet-done{width:100%;margin-top:6px}

  .results{padding:0 0 40px}

  /* The table becomes a list. Same markup, same semantics, different shape:
     a five column row on a 390px screen is unreadable however it is styled. */
  .tablewrap{border-left:0;border-right:0;border-top:0;overflow:visible}
  table.records, table.records tbody, table.records tr, table.records td{
    display:block;width:100%}
  table.records thead{position:absolute;width:1px;height:1px;overflow:hidden;
    clip:rect(0 0 0 0);white-space:nowrap}
  table.records tbody tr{padding:13px 16px;border-bottom:1px solid var(--line);
    display:grid;grid-template-columns:minmax(0,1fr) auto;gap:4px 12px;
    align-items:baseline;min-height:62px}
  table.records td{padding:0;border:0}
  table.records td:first-child{grid-column:1;grid-row:1}
  .records .nm{font-size:15px}
  .records .id{font-size:11px;margin-top:3px}
  /* Versions sit beside the name; the rest becomes one quiet meta line. */
  table.records td.num:not(.hide-xs){grid-column:2;grid-row:1;text-align:right;
    font-size:12px;color:var(--ink2)}
  table.records td.num:not(.hide-xs)::after{content:" versions";
    font-size:10.5px;letter-spacing:.04em}
  table.records td.hide-sm,
  table.records td.hide-xs{display:none}
  tr.skeleton{min-height:62px}
  tr.empty{display:block;padding:34px 18px}

  .results-foot{padding:0 16px;margin-top:12px}
  .results .more{margin:14px 16px 0;width:calc(100% - 32px);min-height:46px}
}

/* The record opens as a sheet from the bottom, the way a phone expects,
   rather than sliding in from an edge that does not exist on a phone. */
@media (max-width: 760px){
  .panel{top:auto;left:0;right:0;bottom:0;width:100%;height:92svh;
    transform:translateY(100%);box-shadow:0 -12px 32px rgba(17,24,39,.2);
    border-top:1px solid var(--ink)}
  .panel.open{transform:none}
  .panel .inner{padding:8px 18px calc(48px + var(--safe-b))}
  .panel .inner::before{content:"";display:block;width:38px;height:4px;
    background:var(--line);margin:6px auto 16px}
  .panel .close{top:6px;right:8px;width:44px;height:44px;border-color:transparent}
  .panel h2{font-size:19px;padding-right:44px}
  .vtable{min-width:0;font-size:13px}
  .vtable th{font-size:10px;padding-right:8px}
  .vtable td{padding:9px 8px 9px 0}
  .vtable td.v{font-size:11.5px}
}

.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.sortsel{font:500 12px/1 var(--mono);letter-spacing:.04em;min-height:38px;
  padding:8px 10px;border:1px solid var(--line);background:var(--bg);
  color:var(--ink);outline:none}
.sortsel:focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
@media (min-width: 900px){ .toolbar, .sheet-scrim, .facet-done{display:none} }

/* ---- portal: browse shelves ----
   Entry points for someone who has not typed anything yet. A ranked list of
   eight, not a wall of seventy thousand. */
.shelves{display:grid;gap:26px}
@media(min-width:1100px){ .shelves{grid-template-columns:1fr 1fr;gap:26px 32px} }
.shelf{background:var(--bg);border:1px solid var(--line)}
.shelf-head{padding:14px 16px;border-bottom:1px solid var(--ink);position:relative}
.shelf-head h2{font:600 15px/1.2 var(--sans);letter-spacing:-.01em;margin:0}
.shelf-head p{margin:6px 0 0;font-size:12.5px;line-height:1.5;color:var(--ink2);
  max-width:56ch}
.shelf-count{display:block;margin-top:8px;font:400 10.5px/1 var(--mono);
  letter-spacing:.08em;text-transform:uppercase;color:var(--ink2)}
.shelf-list{list-style:none;margin:0;padding:0;counter-reset:rank}
.shelf-list li{display:grid;grid-template-columns:28px minmax(0,1fr) auto;
  gap:12px;align-items:baseline;padding:10px 16px;border-bottom:1px solid var(--line);
  cursor:pointer;min-height:48px}
.shelf-list li:last-child{border-bottom:0}
.shelf-list li:hover{background:var(--alt)}
.shelf-list li:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
.shelf-list .rank{font:400 11px/1.6 var(--mono);color:var(--ink2)}
.sh-main{min-width:0;display:flex;flex-direction:column;gap:2px}
.sh-main .nm{font-size:14px;font-weight:500;letter-spacing:-.008em;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sh-main .id{font-family:var(--mono);font-size:10.5px;color:var(--ink2);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sh-meta{font:500 12px/1.4 var(--mono);color:var(--ink);text-align:right;
  font-variant-numeric:tabular-nums;white-space:nowrap}
.sh-meta i{font-style:normal;font-weight:400;color:var(--ink2);font-size:10px;
  display:block;letter-spacing:.04em}

/* usage and badges in the results table */
.records td.used{font-family:var(--mono);font-size:12.5px;white-space:nowrap}
.records td.used span{display:block;font-size:9.5px;color:var(--ink2);
  letter-spacing:.04em;text-transform:uppercase}
.pill.ok{border-color:color-mix(in srgb, var(--accent) 34%, transparent);
  color:var(--accent)}
.records td.badges{max-width:230px}
@media (max-width: 899px){
  .shelves{gap:18px;padding:14px 14px 0}
  .shelf-head{padding:12px 14px}
  .shelf-list li{padding:10px 14px;min-height:52px}
  table.records td.badges{grid-column:1/-1;grid-row:2;display:block;margin-top:2px}
  table.records td.badges .pill{font-size:9.5px;padding:3px 5px}
  table.records td.used{grid-column:2;grid-row:1;text-align:right;display:block}
  table.records td.used span{font-size:9px}
  table.records td.num.hide-xs{display:none}
}

/* ---- charts ---- */
.chartbox{margin:22px 0 0;border:1px solid var(--line);background:var(--bg);padding:14px}
.chartbox svg{display:block;width:100%;height:auto}
.chart-cap{margin-top:12px;padding-top:12px;border-top:1px solid var(--line);
  font:400 12.5px/1.6 var(--mono);color:var(--ink2)}
.chart-cap b{font-weight:500;color:var(--ink)}
@media (max-width:899px){
  .chartbox{padding:10px}
  .chart-cap{font-size:11.5px}
}
/* The line draws itself once, which is the one place motion says something:
   the record accumulating. */
@media (prefers-reduced-motion: no-preference){
  .chartbox path.spark{stroke-dasharray:2400;stroke-dashoffset:2400;
    animation:draw 1.5s cubic-bezier(.22,.8,.3,1) .15s forwards}
}
@keyframes draw{to{stroke-dashoffset:0}}

/* ---- the architecture diagram (brief section 17) ----
   Real text in a ruled flow rather than an image, so it is readable by a
   screen reader, selectable, translatable and correct in both themes without
   a second asset. No network brains, no glowing nodes. */
.arch{display:grid;gap:18px;margin:22px 0 16px;border:1px solid var(--line);
  background:var(--bg);padding:20px}
@media(min-width:760px){ .arch{grid-template-columns:200px minmax(0,1fr);gap:28px;align-items:start} }
.arch-sources{display:flex;flex-direction:column;gap:6px;position:relative}
.arch-sources span{font:400 12px/1.5 var(--mono);color:var(--ink);padding:7px 10px;
  border:1px solid var(--line);background:var(--alt);position:relative}
@media(min-width:760px){
  /* One rule per source, gathering into the first stage. */
  .arch-sources::after{content:"";position:absolute;right:-14px;top:14px;bottom:14px;
    width:1px;background:var(--line)}
  .arch-sources span::after{content:"";position:absolute;right:-14px;top:50%;
    width:14px;height:1px;background:var(--line)}
}
.arch-flow{display:flex;flex-direction:column;gap:0;position:relative}
.arch-node{font:500 13px/1.3 var(--mono);color:var(--ink);padding:11px 14px;
  border:1px solid var(--line);background:var(--bg);position:relative}
.arch-node.head{border-color:var(--ink);font-weight:600}
.arch-node.term{border-color:var(--accent);color:var(--accent)}
.arch-node.side{border-style:dashed;color:var(--ink2)}
/* The connector between stages. */
.arch-flow > *:not(:last-child)::after{content:"";display:block;position:absolute;
  left:26px;bottom:-15px;width:1px;height:15px;background:var(--line)}
.arch-flow > *{margin-bottom:15px}
.arch-flow > *:last-child{margin-bottom:0}
.arch-branch{display:grid;gap:10px}
@media(min-width:620px){ .arch-branch{grid-template-columns:1fr 1fr;gap:14px} }
.arch-branch .arch-node::after{display:none}
.arch + .fine{font-size:12.5px;color:var(--ink2)}

/* ---- the hero flow ----
   Adapted from the animated reference package: sources in, one record, events
   out. Its own palette ran to about thirty colours including teals and
   purples; this is the same composition in the nine brand colours, with the
   event rail using the semantic three it already uses for record states.

   The wires animate as a slow dash flow, which is the only motion here and
   reads as observation arriving rather than decoration. */
.flow{margin:0;display:grid;gap:10px;align-items:center;
  grid-template-columns:minmax(0,1fr)}
@media(min-width:760px){
  .flow{grid-template-columns:minmax(120px,auto) minmax(40px,64px)
        minmax(260px,1.1fr) minmax(40px,64px) minmax(190px,1fr);gap:0}
}
.flow-sources,.flow-events{display:flex;flex-direction:column;gap:6px;margin:0;padding:0;
  list-style:none}
.flow-sources span,.flow-events li{font:400 11.5px/1.35 var(--mono);color:var(--ink2);
  border:1px solid var(--line);background:var(--bg);padding:7px 9px;white-space:nowrap}
.flow-events li{border-left-width:3px;white-space:normal}
.flow-events b{display:block;font-weight:500;font-size:11.5px;color:var(--ink)}
.flow-events small{display:block;font-size:10px;color:var(--ink2);margin-top:2px}
.ev.added{border-left-color:var(--added)}
.ev.changed{border-left-color:var(--changed)}
.ev.removed{border-left-color:var(--removed)}
.ev.neutral{border-left-color:var(--accent)}

.flow-wires{width:100%;height:230px;display:none}
@media(min-width:760px){ .flow-wires{display:block} }
.flow-wires path{fill:none;stroke:var(--line);stroke-width:1;vector-effect:non-scaling-stroke}
@media (prefers-reduced-motion: no-preference){
  .flow-wires path{stroke:var(--accent);stroke-opacity:.5;
    stroke-dasharray:3 7;animation:flowdash 3.2s linear infinite}
  .flow-wires.out path{animation-direction:reverse;animation-duration:3.8s}
}
@keyframes flowdash{to{stroke-dashoffset:-40}}

.flow .specimen{margin:0}
.flow-cap{grid-column:1/-1;margin-top:12px;padding-top:12px;
  border-top:1px solid var(--line);font:400 12px/1.6 var(--mono);color:var(--ink2)}

/* On a phone the three columns become three stacked blocks, and the sources
   and events become chip rows so they do not cost six lines each. */
@media (max-width:759px){
  .flow-sources,.flow-events{flex-direction:row;flex-wrap:wrap;gap:5px}
  .flow-sources span{font-size:10.5px;padding:5px 7px}
  .flow-events li{flex:1 1 46%;padding:7px 8px}
  .flow-events small{display:none}
  .flow-cap{font-size:11px}
}

/* ============================================================
   The approved hero, from the design render.

   This deliberately departs from section 26 of the brief, which rules out
   gradients, glassmorphism, rounded pills and colours beyond the nine. The
   render is the later and more specific instruction, so it governs, and the
   extra colours are confined to the event taxonomy where each one means a
   specific kind of change.
   ============================================================ */
:root{
  --night:#0A1628;
  --night-2:#0D1E36;
  --night-line:rgba(255,255,255,.10);
  --night-ink:#FFFFFF;
  --night-ink2:#9DB2CE;
  --sky:#7FB0FF;          /* the third stratum of the mark, on dark */
  --ev-new:#34D399;
  --ev-changed:#4DA0FF;
  --ev-moved:#A78BFA;
  --ev-gone:#F87171;
}

.hero-band{position:relative;isolation:isolate;overflow:hidden;
  background:var(--night);border-bottom:0;padding:0}
.hero-bg{position:absolute;inset:0;z-index:-1;
  background:
    radial-gradient(900px 420px at 72% 8%, rgba(37,99,235,.30), transparent 62%),
    radial-gradient(700px 380px at 18% 92%, rgba(127,176,255,.14), transparent 60%),
    linear-gradient(180deg, var(--night) 0%, var(--night-2) 58%, var(--night) 100%)}
.hero-bg::after{content:"";position:absolute;inset:0;opacity:.35;
  background-image:linear-gradient(var(--night-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--night-line) 1px, transparent 1px);
  background-size:64px 64px;
  mask-image:radial-gradient(70% 60% at 60% 30%, #000 25%, transparent 75%)}

.hero-inner{display:grid;gap:34px;padding-top:44px;padding-bottom:96px;position:relative}
.hero-inner > *{min-width:0}
@media(min-width:1040px){
  .hero-inner{grid-template-columns:minmax(0,.92fr) minmax(0,1.08fr);
    gap:44px;align-items:center;padding-top:56px;padding-bottom:100px}
}
.marketing .hero-band h1{color:var(--night-ink);font-size:clamp(36px,5.4vw,60px);
  line-height:1.03;letter-spacing:-.035em;max-width:none}
.hero-band h1 em{font-style:normal;color:var(--sky)}
.marketing .hero-band .lede{color:var(--night-ink2);margin-top:18px;
  max-width:46ch;font-size:16.5px}

/* The front page does not search. The portal does, so the hero points at it
   rather than growing a second search field that would land there anyway. */
.hero-act{display:flex;flex-wrap:wrap;align-items:center;gap:10px 22px;margin-top:30px}
.hero-band .hero-act .btn{background:var(--accent);border-color:var(--accent);
  color:#fff;border-radius:999px;font-family:var(--sans);font-weight:500;
  font-size:14px;letter-spacing:0;padding:13px 22px}
.hero-band .hero-act .btn:hover{background:#1D4ED8;border-color:#1D4ED8;color:#fff}
.hero-alt{font:500 14px/1 var(--sans);color:var(--night-ink);border-bottom:1px solid
  rgba(255,255,255,.28);padding-bottom:3px}
.hero-alt:hover{color:var(--sky);border-color:var(--sky);text-decoration:none}
.hero-alt span{display:inline-block;margin-left:5px;transition:transform .18s ease}
.hero-alt:hover span{transform:translateX(3px)}
/* .marketing p outranks a bare class here, which is how the last three colours
   on this hero came out at 3:1. Scope it to the band. */
.marketing .hero-band .hero-meta{margin-top:26px;font:400 12.5px/1.6 var(--mono);
  color:var(--night-ink2);max-width:42ch}

/* ---- the visualisation ---- */
.hero-viz{position:relative;display:grid;gap:12px;min-width:0}
@media(min-width:1240px){
  /* Two columns and a lane between them for the wires. The record and its
     version stack hold column one; the four event cards hold column two; the
     wires are absolutely placed in the gap.

     The fan is geometry, not decoration. Each wire is coloured for one event
     and has to land on that card, so both are positioned from the same four
     numbers:

       block height = 4 * --ev-h + 3 * --ev-gap        = 294px
       card centres = 30, 108, 186, 264                from the block top

     The SVG is given exactly that box and carries viewBox "0 0 136 294" with
     preserveAspectRatio="none", so its user units are those pixels and the
     path endpoints are literally those centres. Changing --ev-h or --ev-gap
     means changing the viewBox and the four d values with them.

     The cards are forced to one height for the same reason: "Artifact
     changed" carries a second line, and at its natural 60px against the
     others' 40px the four centres were not evenly spaced. */
  .hero-viz{--ev-h:60px;--ev-gap:18px;--ev-w:208px;--ev-lane:112px;--ev-top:34px;
    min-height:430px;align-content:start;
    grid-template-columns:minmax(0,1fr) var(--ev-w);column-gap:var(--ev-lane)}
  .rec-card,.rec-stack{grid-column:1;width:auto}
}

.rec-card{background:linear-gradient(160deg, rgba(31,58,102,.92), rgba(14,30,54,.92));
  border:1px solid rgba(127,176,255,.28);border-radius:16px;padding:16px 18px;
  box-shadow:0 18px 44px rgba(3,10,24,.45);position:relative;z-index:2}
.rec-top{display:flex;align-items:center;gap:12px}
.rec-avatar{width:36px;height:36px;border-radius:50%;background:#fff;display:grid;
  place-items:center;flex:0 0 auto}
.rec-avatar svg{width:20px;height:20px;fill:#111827}
.rec-id{min-width:0}
.rec-id span{display:block;font:400 11.5px/1.3 var(--mono);color:var(--night-ink2);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rec-id strong{display:block;font:600 19px/1.2 var(--sans);color:#fff;letter-spacing:-.02em;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rec-mid{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:12px}
.chip-observed{display:inline-flex;align-items:center;gap:7px;border-radius:999px;
  background:rgba(52,211,153,.14);border:1px solid rgba(52,211,153,.4);
  color:#6EE7B7;font:500 11.5px/1 var(--sans);padding:6px 11px}
.chip-observed i{width:6px;height:6px;border-radius:50%;background:var(--ev-new)}
.rec-spark{display:flex;align-items:flex-end;gap:3px;height:26px}
.rec-spark i{width:4px;border-radius:1px;background:var(--sky);opacity:.85;
  height:var(--h)}
.rec-stats{display:flex;gap:18px;margin-top:13px;font:400 12.5px/1 var(--sans);
  color:var(--night-ink2)}
.rec-stats b{color:#fff;font-weight:600;font-family:var(--mono);font-size:13px}
.hero-band .rec-src{margin-top:9px;font:400 11.5px/1.5 var(--mono);
  color:var(--night-ink2)}

.rec-stack{list-style:none;margin:0;padding:0;display:grid;gap:7px;position:relative;z-index:2}
.rec-stack li{display:grid;grid-template-columns:auto 1fr auto;gap:12px;align-items:center;
  background:rgba(255,255,255,.05);border:1px solid var(--night-line);border-radius:12px;
  padding:11px 14px}
.rec-stack .d{font:400 11.5px/1 var(--mono);color:var(--night-ink2);white-space:nowrap}
.rec-stack b{display:flex;align-items:center;gap:8px;font:500 13px/1 var(--mono);color:#fff}
.rec-stack code{font:400 11.5px/1 var(--mono);color:var(--night-ink2)}
.rec-stack .dot{width:7px;height:7px;border-radius:50%;flex:0 0 auto}
.dot.k-new{background:var(--ev-new)} .dot.k-changed{background:var(--ev-changed)}
.dot.k-moved{background:var(--ev-moved)} .dot.k-gone{background:var(--ev-gone)}
.rec-stack .faded{opacity:.45}

.wires{display:none}
@media(min-width:1240px){
  /* The lane between the two columns, and exactly the block the cards
     occupy. It used to be right:100px by 82% of the visualisation, which
     shares no origin with the cards: the wires ran underneath all four and
     came out 4px past their right edge, the red one ending 122px below the
     card it was drawn for and 102px below the whole column, pointing at the
     source rail that used to sit beyond it. */
  .wires{display:block;position:absolute;left:auto;right:var(--ev-w);
    top:var(--ev-top);width:var(--ev-lane);max-width:none;
    height:calc(4 * var(--ev-h) + 3 * var(--ev-gap));z-index:1}
}
.wires .w{fill:none;stroke-width:1.5;vector-effect:non-scaling-stroke;opacity:.75}
.wires .k-new{stroke:var(--ev-new)} .wires .k-changed{stroke:var(--ev-changed)}
.wires .k-moved{stroke:var(--ev-moved)} .wires .k-gone{stroke:var(--ev-gone)}
@media (prefers-reduced-motion: no-preference){
  .wires .w{stroke-dasharray:5 9;animation:flowdash 3.4s linear infinite}
  .wires .k-changed{animation-duration:4.1s} .wires .k-moved{animation-duration:3.8s}
  .wires .k-gone{animation-duration:4.5s}
}

.events{list-style:none;margin:0;padding:0;display:grid;gap:9px;position:relative;z-index:2}
@media(min-width:520px) and (max-width:1239px){ .events{grid-template-columns:1fr 1fr} }
@media(min-width:1240px){
  .events{grid-column:2;grid-row:1/span 2;align-self:start;
    margin-top:var(--ev-top);gap:var(--ev-gap)}
  .ev{min-height:var(--ev-h)}
}
.ev{display:flex;align-items:center;gap:10px;border-radius:12px;padding:11px 13px;
  background:rgba(13,30,54,.86);border:1px solid var(--night-line);
  box-shadow:0 10px 26px rgba(3,10,24,.36)}
.ev{min-width:0}
.ev > div{min-width:0}
.ev b{font:500 12.5px/1.3 var(--sans);color:#fff;display:block;
  white-space:normal;overflow-wrap:anywhere}
.ev small{display:block;font-size:11px;color:var(--night-ink2);margin-top:2px;
  white-space:normal;overflow-wrap:anywhere}
.ev > i{width:9px;height:9px;border-radius:2px;flex:0 0 auto;transform:rotate(45deg)}
/* Named, not initialled. As single letters these collided with .r, the
   site-wide reveal utility that parks an element at opacity 0 until an
   observer reveals it. This page never calls Site.reveals(), so the one
   card that matters most in a historical record, "No longer listed", was
   invisible on the homepage, and the red wire drew 18px low. */
.ev.k-new{border-color:rgba(52,211,153,.45)}   .ev.k-new > i{background:var(--ev-new)}
.ev.k-changed{border-color:rgba(77,160,255,.45)}   .ev.k-changed > i{background:var(--ev-changed)}
.ev.k-moved{border-color:rgba(167,139,250,.45)}  .ev.k-moved > i{background:var(--ev-moved)}
.ev.k-gone{border-color:rgba(248,113,113,.45)}  .ev.k-gone > i{background:var(--ev-gone)}

/* The metrics bar rides the seam between the dark hero and the page.

   No icons here. A cube, a tag, a document and a database cylinder in tinted
   rounded squares is the stock treatment for four numbers, and the icons said
   nothing the labels did not already say. The figures are the content, so they
   are set in the mono face the rest of the record uses for counts and hashes,
   and the cells are divided by rules rather than boxed. */
.metricsband{background:linear-gradient(180deg, var(--night) 0 50%, var(--bg) 50% 100%);
  padding:0;border:0}
.metrics{list-style:none;margin:0;padding:0;display:grid;gap:1px;
  background:var(--line);border:1px solid var(--line);border-radius:16px;overflow:hidden;
  box-shadow:0 14px 40px rgba(3,10,24,.16)}
@media(min-width:760px){ .metrics{grid-template-columns:repeat(4,1fr)} }
@media(max-width:759px){ .metrics{grid-template-columns:1fr 1fr} }
.metrics li{background:var(--panel);padding:22px 20px 20px;
  display:flex;flex-direction:column;gap:7px}
.metrics b{font:500 clamp(24px,2.6vw,31px)/1 var(--mono);letter-spacing:-.025em;
  font-variant-numeric:tabular-nums;color:var(--ink);overflow-wrap:anywhere}
.metrics small{font:400 11.5px/1.35 var(--mono);letter-spacing:.05em;
  text-transform:uppercase;color:var(--ink2)}
@media(max-width:759px){
  .metrics li{padding:16px 15px 15px;gap:5px}
  .metrics b{font-size:21px}
  .metrics small{font-size:10px;letter-spacing:.06em}
}

/* The header sits on the dark hero, so it inverts here. */
.marketing header{background:transparent;border-bottom:0;position:absolute;
  left:0;right:0;top:0;z-index:20;backdrop-filter:none}
.marketing header.stuck{background:rgba(10,22,40,.88);backdrop-filter:saturate(180%) blur(14px);
  position:fixed;border-bottom:1px solid var(--night-line)}
.marketing header nav a{color:#D9E4F5}
.marketing header nav a:hover{color:#fff}
.marketing header nav a.btn{background:var(--accent);border-color:var(--accent);color:#fff;
  border-radius:999px;font-family:var(--sans);font-weight:500;font-size:14px;letter-spacing:0}
.marketing header nav a.btn:hover{background:#1D4ED8;border-color:#1D4ED8}

/* ============================================================
   The dark hero on a phone.

   At 390 it ran 1245px tall against an 844px screen, so the metrics bar sat a
   screen and a half below the fold and the search pill had grown to 113px.
   The aim here is one thumb-scroll to the first real content.
   ============================================================ */
@media (max-width: 899px){
  .hero-inner{padding-top:26px;padding-bottom:62px;gap:24px}
  .marketing .hero-band h1{font-size:clamp(30px,8.2vw,40px);line-height:1.04}
  .hero-band .lede{margin-top:13px;font-size:15px;max-width:none}

  /* Full width and stacked: a 375px screen cannot hold both actions on one
     row without the label wrapping inside the button. */
  .hero-act{margin-top:22px;gap:14px;flex-direction:column;align-items:stretch}
  .hero-band .hero-act .btn{width:100%;min-height:48px}
  .hero-alt{align-self:flex-start}
  .marketing .hero-band .hero-meta{margin-top:18px;font-size:12px}

  .hero-viz{gap:8px}
  .rec-card{padding:13px 14px;border-radius:14px}
  .rec-id strong{font-size:17px}
  .rec-mid{margin-top:10px}
  .rec-stats{margin-top:10px;font-size:12px}
  /* Same specificity trap as above: .marketing p wins over a bare class. */
  .hero-band .rec-src{margin-top:7px;font-size:11px}
  .rec-stack li{padding:9px 12px;border-radius:10px;gap:10px}
  .rec-stack .d{font-size:10.5px}
  .rec-stack b{font-size:12px}
  .rec-stack code{font-size:10.5px}
  /* Three recent versions make the point; the fourth was only there to fade. */
  .rec-stack li.faded{display:none}

  .events{gap:7px}
  .ev{padding:9px 11px;border-radius:10px}
  .ev b{font-size:12px}
  .ev small{font-size:10.5px}

  .metricsband{background:var(--bg)}
  .metrics{border-radius:14px;margin-top:-34px;position:relative;z-index:5}
}

/* ============================================================
   The blog.

   Posts are the only server rendered long form pages on this site, which
   makes them the only thing a crawler can read in full: server records are
   drawn client side and are deliberately out of the sitemap. So these pages
   carry their own structured data and their own measure.
   ============================================================ */
.postlist{list-style:none;margin:0;padding:0;border-top:1px solid var(--line)}
.postlist li{border-bottom:1px solid var(--line)}
.postlist a{display:block;padding:24px 0;color:inherit}
.postlist a:hover{text-decoration:none}
.postlist a:hover h2{color:var(--accent)}
.postlist h2{font-size:clamp(19px,2.2vw,23px);letter-spacing:-.02em;margin:0;
  transition:color .15s}
.postlist p{margin-top:8px;color:var(--ink2);font-size:15px;max-width:68ch}
.post-meta{font:400 11.5px/1.5 var(--mono);letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink2);display:flex;gap:14px;flex-wrap:wrap;align-items:baseline}
.post-meta .tag{color:var(--accent)}
@media(max-width:600px){ .postlist a{padding:18px 0} }

/* .hero h1 is capped at 17ch site wide, which is right for a three word
   product headline and wrong for a sentence: it broke "Why we keep the
   receipts" across three lines. */
.post-hero h1{max-width:26ch}
.post-hero .lede{max-width:66ch}
.post-hero .post-meta{margin-bottom:18px}
.post-hero .post-sub{margin:10px 0 0;font:400 clamp(17px,2vw,19px)/1.4 var(--sans);
  color:var(--ink2);letter-spacing:-.01em;max-width:40ch}

.post{max-width:70ch}
.post pre{margin:22px 0 0;padding:16px 18px;background:var(--alt);
  border:1px solid var(--line);overflow-x:auto}
.post pre code{font:400 13px/1.7 var(--mono);color:var(--ink);background:none;
  padding:0;white-space:pre}
.post :not(pre) > code{font:400 13.5px/1.4 var(--mono);background:var(--alt);
  padding:2px 5px;overflow-wrap:anywhere}
.post table.records{margin-top:24px;width:100%}
.post > p{margin-top:18px;color:var(--ink2);font-size:16.5px;line-height:1.7}
.post h2{font-size:clamp(20px,2.4vw,25px);margin-top:44px;letter-spacing:-.02em}
.post h3{font-size:17px;margin-top:30px}
.post ul,.post ol{margin:16px 0 0;padding-left:22px;color:var(--ink2);line-height:1.7}
.post li{margin-top:9px}
.post li strong,.post p strong{color:var(--ink);font-weight:600}
.post a{color:var(--accent)}
.post figure{margin:26px 0 0}
.post figcaption{font:400 12px/1.5 var(--mono);color:var(--ink2);margin-top:8px}

/* Quoted upstream fact. Always attributed, never paraphrased into a claim
   of our own: the difference between reporting and asserting is the whole
   editorial position of this site. */
.post blockquote{margin:24px 0 0;padding:16px 20px;background:var(--alt);
  border-left:3px solid var(--accent)}
.post blockquote p{margin:0;color:var(--ink);font-size:15.5px;line-height:1.65}
.post blockquote cite{display:block;margin-top:10px;font-style:normal;
  font:400 12px/1.5 var(--mono);color:var(--ink2)}

/* A figure taken from the record, as opposed to one taken from a source. */
.from-record{margin:26px 0 0;border:1px solid var(--line);background:var(--panel)}
.from-record .fr-head{font:500 11px/1 var(--mono);letter-spacing:.12em;
  text-transform:uppercase;color:var(--ink2);padding:12px 18px;
  border-bottom:1px solid var(--line)}
.from-record dl{margin:0;padding:16px 18px;display:grid;gap:10px 20px}
@media(min-width:560px){ .from-record dl{grid-template-columns:auto 1fr} }
.from-record dt{font:400 12.5px/1.4 var(--mono);color:var(--ink2);margin:0}
.from-record dd{margin:0;font:500 14px/1.4 var(--sans);color:var(--ink);
  font-variant-numeric:tabular-nums;overflow-wrap:anywhere}

/* The standing note under anything that names a third party. */
.post .caveat{margin-top:26px;padding:14px 18px;border:1px dashed var(--line);
  font-size:14.5px;line-height:1.65;color:var(--ink2)}
.post .caveat strong{color:var(--ink)}

.post-foot{margin-top:52px;padding-top:24px;border-top:1px solid var(--line);
  display:flex;gap:16px;flex-wrap:wrap;align-items:center;
  font:400 13px/1.5 var(--sans);color:var(--ink2)}
.post-foot a{color:var(--accent)}

/* ============================================================
   Mailing list signup.

   Appears where intent already exists: at the end of a post, and on the blog
   index. Not on the portal, where someone is mid-investigation and a form is
   an interruption.
   ============================================================ */
.signup{margin:0;padding:22px 24px;border:1px solid var(--line);background:var(--alt)}
.signup h3{margin:0;font-size:16px;letter-spacing:-.015em}
.signup .lead{margin:6px 0 0;font-size:14.5px;color:var(--ink2);max-width:52ch}
.signup-row{display:flex;gap:8px;margin-top:14px;flex-wrap:wrap}
.signup-row input[type=email]{flex:1 1 220px;min-width:0;font:400 15px/1.4 var(--sans);
  color:var(--ink);background:var(--bg);border:1px solid var(--line);padding:11px 13px;
  outline:none;transition:border-color .15s}
.signup-row input[type=email]:focus{border-color:var(--accent)}
.signup-row button{flex:0 0 auto;border:0;background:var(--accent);color:#fff;
  font:500 14px/1 var(--sans);padding:12px 20px;cursor:pointer;min-height:44px;
  transition:background .15s}
.signup-row button:hover:not(:disabled){background:#1D4ED8}
.signup-row button:disabled{opacity:.6;cursor:default}
.signup-note{margin:10px 0 0;font-size:12.5px;color:var(--ink2);max-width:56ch}
.signup-msg{margin:10px 0 0;font-size:13.5px;min-height:1.2em}
.signup-msg.ok{color:var(--added)}
.signup-msg.bad{color:var(--removed)}
/* Off screen rather than display:none, which a bot filling every field will
   skip. This one is only ever filled by something that is not reading. */
.signup .hp{position:absolute;left:-9999px;width:1px;height:1px;opacity:0}
@media(max-width:600px){
  .signup{padding:18px 16px}
  .signup-row button{width:100%}
}
