/* MB Lab Technology — site styles
   Palette from the invoice/quote templates, dressed as test-bench equipment:
   squared geometry, a monospace annotation layer, graph-paper ground and a
   copper accent. No framework, no CDN, no webfont — one stylesheet. */

:root {
  --ink:      #0d1522;   /* the diagram ink, one step lighter */
  --muted:    #455a72;
  --muted-2:  #32485f;
  --sky:      #a9c3e0;   /* body text on the dark grounds. --muted-2 and --navy
                            are picked to pass on paper and are unreadable on
                            --ink: .sub measured 1.94:1 and a figcaption link
                            1.77:1, against a 4.5:1 minimum. This is 10.08:1,
                            and being blue rather than white it keeps the step
                            down from the white headline. */
  --navy:     #1e3a8a;
  --copper:   #974106;   /* the electrical accent — used sparingly.
                            Darker than the diagrams' #b45309, which
                            does not clear AA on paper this deep. */
  --copper-l: #f59e0b;   /* copper on dark ground */
  --bg:       #e2eaf3;   /* paper, well off white - glare is tiring */
  --bg-soft:  #d5dfed;   /* blueprint paper, the darker band */
  --bg-soft2: #c9d6e7;
  --line:     #bccee3;
  --card:     #ebf2f9;   /* lifts off the paper without glaring */
  --grid:     rgba(30, 58, 138, 0.075);
  --grid-d:   rgba(148, 163, 184, 0.07);

  --font: "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
  --mono: "Cascadia Mono", "Consolas", ui-monospace, "SF Mono", "Menlo",
          "DejaVu Sans Mono", monospace;
  --wrap: 1080px;
  --gutter: 24px;
}

*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: var(--font);
  font-size: 17px;
  line-height: 1.6;
  color: var(--ink);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 { line-height: 1.2; margin: 0; letter-spacing: -0.02em; }
p { margin: 0 0 1em; }
a { color: var(--navy); }

.wrap { max-width: var(--wrap); margin: 0 auto; padding: 0 var(--gutter); }

/* Monospace annotation layer — every label on this site reads like something
   silkscreened onto a board rather than set in a brochure. */
.eyebrow {
  font-family: var(--mono);
  font-size: 11.5px; font-weight: 600; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--copper);
  margin: 0 0 16px; display: flex; align-items: center; gap: 12px;
}
.eyebrow::after {
  content: ""; height: 1px; flex: 1; max-width: 120px;
  background: repeating-linear-gradient(90deg,
    var(--line) 0 4px, transparent 4px 8px);
}

/* ---------------------------------------------------------------- header - */
.site-header {
  position: sticky; top: 0; z-index: 10;
  /* Glass, from the mock-up: the drawing underneath stays faintly visible
     as the page scrolls past. The colour is still opaque enough to read
     against on a browser with no backdrop-filter. */
  background: rgba(13, 21, 34, 0.86);
  -webkit-backdrop-filter: blur(14px) saturate(130%);
          backdrop-filter: blur(14px) saturate(130%);
  border-bottom: 1px solid rgba(245, 158, 11, 0.28);
}
@supports not (backdrop-filter: blur(1px)) {
  .site-header { background: rgba(13, 21, 34, 0.97); }
}
.site-header .wrap {
  display: flex; align-items: center; justify-content: space-between;
  gap: 24px; height: 68px;
  /* Wider than --wrap, and only here. The body keeps 1080 because that is a
     reading measure for prose; the header is a row of twelve links and a
     button. At 1080 it wanted 1088, so the button broke into GET / IN / TOUCH
     on every window from 1280 upward - and a bigger screen did not help,
     because the container was capped at 1080 whatever the screen. */
  max-width: 1240px;
}
.brand { display: flex; align-items: center; color: #fff; text-decoration: none; }
.brand .sr { position: absolute; left: -9999px; }

.logo-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
.logo-mark { display: block; color: inherit; aspect-ratio: 3507 / 1598; }
.brand .logo-mark { height: 38px; }
.site-footer .logo-mark { height: 26px; color: var(--muted); }

.site-nav { display: flex; gap: 22px; align-items: center; }
/* Twelve nav items want about 1022 px of window at full size. Rather than drop
   them at the first sign of trouble they are tightened in two steps, which
   carries the full set down to 881 px with nothing overflowing. Measured, at
   every width from 375 to 1920. */
@media (max-width: 1180px) {
  .site-nav { gap: 13px; }
  .site-nav a:not(.cta) { font-size: 12px; letter-spacing: 0.04em; }
}
@media (max-width: 1020px) {
  .site-nav { gap: 9px; }
  .site-nav a:not(.cta) { font-size: 11px; letter-spacing: 0.01em; }
  .site-nav a.cta { padding: 9px 12px; }
}
/* Below this the squeeze has run out: the links go and the button stays. A
   block of its own, because the existing 860 px block that also hides them
   carries grids, the contact panel, sections and the hero - changing ITS
   breakpoint would move all of that too, which is what a first attempt did. */
@media (max-width: 880px) {
  .site-nav a:not(.cta) { display: none; }
  .site-nav { gap: 18px; }
  .site-nav a.cta { padding: 9px 18px; }
}
.site-nav a {
  color: rgba(255,255,255,0.78); text-decoration: none;
  font-family: var(--mono); font-size: 12.5px; font-weight: 500;
  letter-spacing: 0.06em; text-transform: uppercase;
}
.site-nav a:hover { color: var(--copper-l); }
.site-nav a.cta {
  color: var(--ink); background: var(--copper-l);
  padding: 9px 18px; border: 1px solid var(--copper-l);
  white-space: nowrap;      /* three words on one line, at any width */
}
.site-nav a.cta:hover { background: transparent; color: var(--copper-l); }

/* ------------------------------------------------------------------ hero - */
.hero {
  position: relative; overflow: hidden;
  background: var(--ink);
  color: #fff;
  padding: 100px 0 108px;
  border-bottom: 1px solid rgba(245, 158, 11, 0.3);
}
/* graph-paper ground, as on a drawing sheet */
.hero::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background-image:
    linear-gradient(var(--grid-d) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-d) 1px, transparent 1px);
  background-size: 48px 48px;
  -webkit-mask-image: radial-gradient(ellipse 80% 70% at 30% 40%, #000 30%, transparent 78%);
          mask-image: radial-gradient(ellipse 80% 70% at 30% 40%, #000 30%, transparent 78%);
}
.hero .wrap { position: relative; }

.hero h1 {
  font-size: clamp(32px, 5.2vw, 54px);
  font-weight: 700; max-width: 17ch; margin-bottom: 24px;
}
.hero .lede {
  font-size: clamp(17px, 2.1vw, 20px);
  color: rgba(255,255,255,0.80);
  max-width: 62ch; margin-bottom: 36px;
}
.hero .lede strong { color: #fff; font-weight: 600; }

.actions { display: flex; flex-wrap: wrap; gap: 14px; }
.btn {
  display: inline-block; padding: 14px 28px;
  font-family: var(--mono); font-size: 13px; font-weight: 600;
  letter-spacing: 0.08em; text-transform: uppercase;
  text-decoration: none; border: 1px solid transparent;
  transition: background .15s, color .15s, border-color .15s;
}
.btn-primary { background: var(--copper-l); color: var(--ink); border-color: var(--copper-l); }
.btn-primary:hover { background: transparent; color: var(--copper-l); }
.btn-ghost { border-color: rgba(255,255,255,0.32); color: #fff; }
.btn-ghost:hover { border-color: #fff; background: rgba(255,255,255,0.08); }

/* spec strip — reads like a rating plate */
.hero-meta {
  margin-top: 46px; padding-top: 22px;
  border-top: 1px solid rgba(255,255,255,0.16);
  display: flex; flex-wrap: wrap; gap: 14px 38px;
  font-family: var(--mono); font-size: 12px; letter-spacing: 0.03em;
  color: rgba(255,255,255,0.58);
}
.hero-meta span { display: inline-flex; align-items: center; gap: 9px; }
.hero-meta span::before {
  content: ""; width: 6px; height: 6px; background: var(--copper-l); flex: none;
}
.hero-meta b { color: rgba(255,255,255,0.94); font-weight: 600; }

/* --------------------------------------------------------------- sections - */
section { padding: 88px 0; position: relative; }
section.soft {
  background-color: var(--bg-soft);
  border-block: 1px solid var(--line);
  background-image:
    linear-gradient(var(--grid) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid) 1px, transparent 1px);
  background-size: 40px 40px;
}
/* The drawing sheet, generated by _site_source/make_blueprint_svg.py.
   It is masked away across the whole text column - 1080px of .wrap plus a
   100px fade either side - so a fragment can never sit under a sentence.
   Below 1200px there is no margin left to draw in and it disappears, which
   is the right answer on a phone anyway. */
section.soft::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background-image: url("shots/blueprint.svg");
  background-size: 1200px 900px;
  background-position: center top;
}
section.soft:nth-of-type(even)::before { background-position: 320px -180px; }
section.soft > .wrap { position: relative; }

/* Where text is laid over the drawing, show the band's own blue behind it
   and nothing else. --tg is the ground and it inherits, so anything that
   already has a ground of its own - a card, a figure, a bordered table -
   switches it off for its whole subtree rather than having to be listed
   against every text element. --tgp does the same for the padding that
   makes the blue reach past the glyphs; it is handed straight back as a
   negative margin, so nothing on the page moves. Between the blocks the
   drawing is still there, which is the point. */
section.soft { --tg: var(--bg-soft); --tgp: 12px; }

section.soft :is(.app-card, .app-hero, .app-thumb, .card, .caveat,
                 .contact-panel, .cta, .edition, .editions, .enquiry,
                 .form-card, .fund, .funds, .hero, .hero-meta, .hub,
                 .pillar, .post pre, .post table, .post code, .proto,
                 .proto-wrap, .shot, .shot-band, .soon, .soon-grid, .stat,
                 .stats, .todo, .tool, .tools, .vs, .vs-wrap,
                 figure, table, pre, blockquote) {
  --tg: transparent;
  --tgp: 0px;
}

section.soft :is(h1, h2, h3, h4, p, li, dt, dd, figcaption,
                 .eyebrow, .sub, .note, .tools-head, .cat-head, .hw-sub,
                 .encl, .app-tagline) {
  background-color: var(--tg);
  padding-inline: var(--tgp);
  margin-inline: calc(-1 * var(--tgp));
}

/* A bordered or already-framed thing takes the colour but never the
   padding, or its frame grows 24px wider than the column. */
section.soft :is(.hw-nav, .proto-wrap, .vs-wrap, .btn-outline, .btn-ghost,
                 .rel, .spec, .ticks li) {
  background-color: var(--bg-soft);
}

/* .btn-ghost is drawn for a dark ground - white text, white-ish border.
   On a light band it was invisible long before the drawing went behind it.
   On anything but the dark heroes it behaves like .btn-outline. */
section:not(.hero):not(.app-hero) .btn-ghost {
  color: var(--ink); border-color: var(--ink);
}
section:not(.hero):not(.app-hero) .btn-ghost:hover {
  background: var(--ink); color: #fff; border-color: var(--ink);
}

/* The containers stay transparent so the drawing shows in the gaps. */
section.soft :is(.section-head, .chain, .chain-step, .actions, .grid) {
  background: none;
}

.section-head { max-width: 62ch; margin-bottom: 50px; }
.section-head h2 { font-size: clamp(26px, 3.4vw, 34px); margin-bottom: 14px; }
.section-head p { color: var(--muted-2); margin: 0; }
.section-head p + p { margin-top: 14px; }

/* ------------------------------------------------------------------ grid - */
.grid { display: grid; gap: 22px; }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-2 { grid-template-columns: repeat(2, 1fr); }

/* panels with corner registration marks, like a fab drawing */
.card {
  position: relative; background: var(--card);
  border: 1px solid var(--line); padding: 30px 28px 28px;
}
.card::before, .card::after {
  content: ""; position: absolute; width: 9px; height: 9px;
  border-color: var(--copper); border-style: solid;
}
.card::before { top: -1px; left: -1px; border-width: 1px 0 0 1px; }
.card::after  { bottom: -1px; right: -1px; border-width: 0 1px 1px 0; }
.card h3 { font-size: 18px; margin-bottom: 10px; }
.card p { color: var(--muted-2); font-size: 15px; margin: 0; }
.card .num {
  font-family: var(--mono); font-size: 11.5px; font-weight: 600;
  color: var(--copper); letter-spacing: 0.14em;
  display: block; margin-bottom: 14px;
}

/* ------------------------------------------------------------ capability - */
.cap {
  border-left: 2px solid var(--navy); padding: 2px 0 2px 22px;
  position: relative;
}
.cap::before {
  content: ""; position: absolute; left: -2px; top: 0;
  width: 2px; height: 26px; background: var(--copper);
}
.cap h3 { font-size: 19px; margin-bottom: 8px; }
.cap p { color: var(--muted-2); font-size: 15px; margin-bottom: 12px; }
.cap ul { margin: 0; padding: 0; list-style: none; }
.cap li {
  color: var(--muted-2); font-size: 14.5px; margin-bottom: 7px;
  padding-left: 18px; position: relative;
}
.cap li::before {
  content: ""; position: absolute; left: 0; top: 0.62em;
  width: 7px; height: 1px; background: var(--copper);
}

/* --------------------------------------------------------------- software - */
/* laid out like a parts table */
.tools {
  display: grid; grid-template-columns: repeat(2, 1fr);
  border: 1px solid var(--line); background: var(--card);
}
.tool { padding: 24px 26px; border-bottom: 1px solid var(--line); }
.tool:nth-child(odd) { border-right: 1px solid var(--line); }
.tool:nth-last-child(-n+2) { border-bottom: 0; }
.tool h3 {
  font-size: 16px; margin-bottom: 7px;
  display: flex; align-items: baseline; gap: 10px;
}
.tool h3::before {
  content: attr(data-ref);
  font-family: var(--mono); font-size: 11px; font-weight: 600;
  color: var(--copper); letter-spacing: 0.1em; flex: none;
}
.tool p { font-size: 14px; color: var(--muted-2); margin: 0; }

.note {
  margin-top: 24px; font-size: 14px; color: var(--muted);
  border-left: 2px solid var(--copper); padding-left: 16px;
}

/* ---------------------------------------------------------------- process - */
.steps { counter-reset: step; display: grid; }
.step {
  display: grid; grid-template-columns: 74px 1fr; gap: 20px;
  padding: 24px 0; border-bottom: 1px solid var(--line);
}
.step:last-child { border-bottom: 0; }
.step .n {
  counter-increment: step;
  font-family: var(--mono); font-size: 12px; font-weight: 600;
  color: var(--copper); letter-spacing: 0.1em; padding-top: 4px;
}
.step .n::before { content: "STEP " counter(step, decimal-leading-zero); }
.step h3 { font-size: 17px; margin-bottom: 6px; }
.step p { color: var(--muted-2); font-size: 15px; margin: 0; }

/* ------------------------------------------------------------------ about - */
.about-body { max-width: 68ch; }
.about-lead { font-size: 20px; font-weight: 600; margin-bottom: 18px; color: var(--ink); }
.about-body p { color: var(--muted-2); }
.fill {
  font-family: var(--mono); font-size: 0.86em; font-weight: 600;
  color: var(--copper); background: #fff7ed;
  border-bottom: 1px dashed var(--copper); padding: 1px 3px;
}

/* ---------------------------------------------------------------- contact - */
.contact-panel {
  background: var(--ink); color: #fff;
  padding: 54px 48px; position: relative; overflow: hidden;
  display: grid; grid-template-columns: 1.15fr 1fr; gap: 56px; align-items: start;
  border-top: 1px solid var(--copper-l);
}
.contact-panel::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background-image:
    linear-gradient(var(--grid-d) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-d) 1px, transparent 1px);
  background-size: 40px 40px;
  -webkit-mask-image: radial-gradient(ellipse 70% 90% at 85% 30%, #000 20%, transparent 75%);
          mask-image: radial-gradient(ellipse 70% 90% at 85% 30%, #000 20%, transparent 75%);
}
.contact-panel > * { position: relative; }
.contact-panel h2 { font-size: clamp(24px, 3vw, 32px); margin-bottom: 14px; }
.contact-panel p { color: rgba(255,255,255,0.75); margin-bottom: 0; }
.contact-list { display: grid; gap: 20px; }
.contact-row { display: grid; gap: 4px; }
.contact-row .k {
  font-family: var(--mono); font-size: 11px; font-weight: 600;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--copper-l);
}
.contact-row .v { font-size: 16px; }
.contact-row a {
  color: #fff; text-decoration: none;
  border-bottom: 1px solid rgba(255,255,255,0.28);
}
.contact-row a:hover { border-color: var(--copper-l); color: var(--copper-l); }

/* ----------------------------------------------------------------- footer - */
.site-footer {
  border-top: 1px solid var(--line); padding: 32px 0;
  font-family: var(--mono); font-size: 12px; letter-spacing: 0.03em;
  color: var(--muted);
}
.site-footer .wrap {
  display: flex; flex-wrap: wrap; gap: 16px 24px;
  justify-content: space-between; align-items: center;
}

/* -------------------------------------------------------------- TODO flag - */
.todo {
  margin-top: 34px; max-width: 68ch;
  background: #fff7ed; border: 1px dashed var(--copper);
  padding: 20px 22px; font-size: 14.5px; color: #7c2d12;
}
.todo b {
  display: block; margin-bottom: 8px;
  font-family: var(--mono); font-size: 11px; font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase;
}

/* ------------------------------------------------------------ responsive - */
@media (max-width: 860px) {
  .grid-3, .grid-2, .tools { grid-template-columns: 1fr; }
  .tool { border-right: 0 !important; }
  .tool:nth-last-child(2) { border-bottom: 1px solid var(--line); }
  .contact-panel { grid-template-columns: 1fr; gap: 36px; padding: 38px 26px; }
  .site-nav { gap: 18px; }
  .site-nav a:not(.cta) { display: none; }
  section { padding: 62px 0; }
  .hero { padding: 70px 0 78px; }
  .step { grid-template-columns: 1fr; gap: 6px; }
}
@media (max-width: 520px) {
  :root { --gutter: 18px; }
  body { font-size: 16px; }
  .eyebrow::after { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { transition: none !important; }
}


/* ======================================================= PHASE 2: software =
   Product pages. Same vocabulary as the home page - mono annotations, copper
   accent, squared panels - with forms and an edition ladder added. */

.app-hero {
  background: var(--ink); color: #fff;
  padding: 68px 0 62px; position: relative; overflow: hidden;
  border-bottom: 1px solid rgba(245, 158, 11, 0.3);
}
.app-hero::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background-image:
    linear-gradient(var(--grid-d) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-d) 1px, transparent 1px);
  background-size: 44px 44px;
  -webkit-mask-image: radial-gradient(ellipse 70% 80% at 25% 40%, #000 25%, transparent 78%);
          mask-image: radial-gradient(ellipse 70% 80% at 25% 40%, #000 25%, transparent 78%);
}
.app-hero .wrap { position: relative; }
.app-hero .eyebrow { color: var(--copper-l); }
.app-hero .eyebrow a { color: inherit; text-decoration: none; border-bottom: 1px solid currentColor; }
.app-hero .eyebrow::after { background: repeating-linear-gradient(90deg,
  rgba(255,255,255,0.28) 0 4px, transparent 4px 8px); }
.app-hero h1 { font-size: clamp(28px, 4.4vw, 44px); margin-bottom: 14px; }
.app-tagline {
  font-size: clamp(16px, 2vw, 19px); color: rgba(255,255,255,0.78);
  max-width: 64ch; margin-bottom: 22px;
}
.app-status {
  font-family: var(--mono); font-size: 12.5px; color: rgba(255,255,255,0.6);
  display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin: 0;
}
.app-status code { color: var(--copper-l); }

.pill {
  /* inline-block, not inline: a bordered badge whose text wraps would otherwise
     have its border drawn around each line fragment. */
  display: inline-block;
  font-family: var(--mono); font-size: 11px; font-weight: 600;
  letter-spacing: 0.1em; text-transform: uppercase;
  padding: 4px 9px; border: 1px solid currentColor; flex: none;
}
.pill-shipping { color: #34d399; }
.pill-early    { color: var(--copper-l); }
.pill-dev      { color: #94a3b8; }
section:not(.app-hero) .pill-shipping { color: #047857; }
section:not(.app-hero) .pill-early    { color: var(--copper); }
section:not(.app-hero) .pill-dev      { color: var(--muted); }

/* two-column body ---------------------------------------------------------- */
.two-col { display: grid; grid-template-columns: 1.5fr 1fr; gap: 48px; align-items: start; }
.two-col h2 { font-size: 24px; margin-bottom: 14px; }
.two-col > div > p, .sub { color: var(--muted-2); }
.sub { max-width: 68ch; }

.why {
  background: var(--bg-soft); border-left: 2px solid var(--copper);
  padding: 22px 24px;
}
.why p:last-child { margin: 0; color: var(--muted-2); font-size: 15px; }

ul.ticks { list-style: none; margin: 18px 0 0; padding: 0; }
ul.ticks li {
  position: relative; padding-left: 20px; margin-bottom: 9px;
  color: var(--muted-2); font-size: 15px;
}
ul.ticks li::before {
  content: ""; position: absolute; left: 0; top: 0.62em;
  width: 8px; height: 1px; background: var(--copper);
}

/* editions ----------------------------------------------------------------- */
.editions { display: grid; grid-template-columns: repeat(3, 1fr);
            border: 1px solid var(--line); background: var(--card); }
.edition { padding: 24px 24px 26px; border-right: 1px solid var(--line); }
.edition:last-child { border-right: 0; }
.edition-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 10px; margin-bottom: 12px; padding-bottom: 10px;
  border-bottom: 1px solid var(--line);
}
.edition-head h3 { font-size: 17px; }
.edition-price {
  font-family: var(--mono); font-size: 11px; font-weight: 600;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--copper);
}
.edition p { font-size: 14.5px; color: var(--muted-2); margin: 0; }

/* forms -------------------------------------------------------------------- */
/* One card since the per-seat quote card went: .forms used to take its
   display:grid from .two-col, so without it the two-column rule here was
   inert. Stated explicitly instead of left to be puzzled over. */
.forms { display: grid; gap: 28px; grid-template-columns: 1fr; }
.form-card { border: 1px solid var(--line); padding: 30px 28px; background: var(--card); position: relative; }
.form-card::before {
  content: ""; position: absolute; top: -1px; left: -1px;
  width: 9px; height: 9px; border: 1px solid var(--copper);
  border-width: 1px 0 0 1px;
}
.muted-card { background: var(--bg-soft); }
.form-card h2 { font-size: 20px; margin-bottom: 8px; }

.form-lead { font-size: 14.5px; color: var(--muted-2); margin-bottom: 18px; }
.enquiry label {
  display: block; margin-bottom: 14px;
  font-family: var(--mono); font-size: 11px; font-weight: 600;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted);
}
/* #cbd5e1 is a colour for a dark ground, and this label sits on --card:
   1.32:1, which is not readable at all. --muted is the paper equivalent
   and measures 6.29:1 there. */
.enquiry .opt { color: var(--muted); letter-spacing: 0.06em; }
.enquiry input, .enquiry select, .enquiry textarea {
  display: block; width: 100%; margin-top: 6px;
  font-family: var(--font); font-size: 15px; letter-spacing: normal;
  text-transform: none; color: var(--ink);
  padding: 10px 12px; border: 1px solid var(--line); background: var(--card);
  border-radius: 0;
}
.enquiry input:focus, .enquiry select:focus, .enquiry textarea:focus {
  outline: 2px solid var(--copper); outline-offset: -2px; border-color: var(--copper);
}
.enquiry textarea { resize: vertical; }
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.enquiry button { cursor: pointer; margin-top: 4px; }
.btn-outline {
  background: transparent; color: var(--ink); border-color: var(--ink);
}
.btn-outline:hover { background: var(--ink); color: #fff; }
.form-fallback {
  margin: 14px 0 0; font-size: 12.5px; color: var(--muted); line-height: 1.5;
}

/* app index ---------------------------------------------------------------- */
.app-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
.app-card {
  display: block; text-decoration: none; color: inherit;
  border: 1px solid var(--line); padding: 22px 22px 24px; background: var(--card);
  transition: border-color .15s, transform .15s;
}
.app-card:hover { border-color: var(--copper); transform: translateY(-2px); }
.app-card-top {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; margin-bottom: 14px;
}
.app-card code { font-family: var(--mono); font-size: 12px; color: var(--copper); }
.app-card h3 { font-size: 17px; margin-bottom: 7px; }
.app-card p { font-size: 14px; color: var(--muted-2); margin: 0; }

/* related ------------------------------------------------------------------ */
.related { display: grid; gap: 10px; margin-top: 18px; }
.rel {
  display: grid; gap: 2px; text-decoration: none; color: inherit;
  border-left: 2px solid var(--line); padding: 6px 0 6px 14px;
}
.rel:hover { border-color: var(--copper); }
.rel b { font-size: 15px; }
.rel span { font-size: 13.5px; color: var(--muted); }

@media (max-width: 980px) {
  .app-grid { grid-template-columns: repeat(2, 1fr); }
  .editions { grid-template-columns: 1fr; }
  .edition { border-right: 0; border-bottom: 1px solid var(--line); }
  .edition:last-child { border-bottom: 0; }
}
@media (max-width: 860px) {
  .two-col, .forms { grid-template-columns: 1fr; gap: 32px; }
  .app-grid { grid-template-columns: 1fr; }
  .field-row { grid-template-columns: 1fr; gap: 0; }
}


/* ------------------------------------------------- screenshots and proof - */
/* A real screenshot of the application, framed like an instrument panel.
   Apps with no screenshot simply do not get this band - never a mock-up. */
.shot-band { padding: 0; background: var(--ink); }
.shot-band .wrap { padding-top: 54px; padding-bottom: 54px; }
.shot {
  margin: 0; border: 1px solid rgba(245, 158, 11, 0.35);
  background: #0b111d; padding: 10px;
}
.shot img {
  display: block; width: 100%; height: auto;
  border: 1px solid rgba(255,255,255,0.08);
}
.shot figcaption {
  margin-top: 12px; padding: 0 4px 2px;
  font-family: var(--mono); font-size: 12px; line-height: 1.6;
  color: rgba(255,255,255,0.62);
}

.stats {
  display: grid; grid-template-columns: repeat(4, 1fr);
  border: 1px solid var(--line); background: var(--card); margin-top: 26px;
}
.stat { padding: 22px 20px; border-right: 1px solid var(--line); }
.stat:last-child { border-right: 0; }
.stat b {
  display: block; font-size: 30px; line-height: 1.1;
  color: var(--ink); letter-spacing: -0.03em;
}
.stat span {
  display: block; margin-top: 6px;
  font-family: var(--mono); font-size: 11.5px; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--muted);
}

/* the dispatcher card leads the index and says why it is different */
.app-card.hub {
  grid-column: 1 / -1;
  background: var(--ink); color: #fff; border-color: var(--copper-l);
}
.app-card.hub:hover { border-color: #fff; }
.app-card.hub h3 { font-size: 21px; }
.app-card.hub p { color: rgba(255,255,255,0.74); font-size: 15px; }
.app-card.hub code { color: var(--copper-l); }

@media (max-width: 860px) {
  .stats { grid-template-columns: repeat(2, 1fr); }
  .stat:nth-child(2) { border-right: 0; }
  .stat:nth-child(-n+2) { border-bottom: 1px solid var(--line); }
  .shot-band .wrap { padding-top: 34px; padding-bottom: 34px; }
}


/* ---------------------------------------- screenshots on the light pages - */
/* Same frame as the dark shot-band, inverted for a white section. */
.shot-light {
  border-color: var(--line); background: var(--bg-soft);
  margin: 0 0 34px;
}
.shot-light img { border-color: var(--line); }
.shot-light figcaption { color: var(--muted); }

/* card thumbnails on the software index */
.app-card.has-thumb { padding-top: 0; overflow: hidden; }
.app-thumb {
  display: block; margin: 0 -22px 18px; background: var(--bg-soft2);
  border-bottom: 1px solid var(--line); overflow: hidden;
}
.app-thumb img {
  display: block; width: 100%; height: 132px;
  object-fit: cover; object-position: top left;
  transition: transform .25s ease;
}
.app-card.has-thumb:hover .app-thumb img { transform: scale(1.03); }

.shot + .shot { margin-top: 26px; }


/* ------------------------------------------------------------------ blog -
   Working notes. Plain prose in the same measure as the rest of the site, so
   a post reads like the pages around it rather than like a CMS theme. */
.post-list { display: grid; gap: 0; border-top: 1px solid var(--line); }
.post-card {
  display: block; padding: 22px 0; border-bottom: 1px solid var(--line);
  text-decoration: none; color: inherit;
}
.post-card:hover h2 { color: var(--copper); }
.post-date {
  font-family: var(--mono); font-size: 11.5px; letter-spacing: 0.1em;
  color: var(--muted);
}
.post-card h2 { margin: 6px 0 6px; font-size: 21px; letter-spacing: -0.02em; }
.post-card p { margin: 0; color: var(--muted); max-width: 70ch; }

.post { max-width: 72ch; font-size: 16.5px; line-height: 1.75; }
.post h2 { margin: 34px 0 12px; font-size: 23px; letter-spacing: -0.02em; }
.post h3 { margin: 26px 0 10px; font-size: 18px; }
.post p { margin: 0 0 16px; }
.post ul, .post ol { margin: 0 0 16px; padding-left: 22px; }
.post li { margin-bottom: 7px; }
.post code {
  font-family: var(--mono); font-size: 0.88em;
  background: var(--bg-soft); padding: 1px 5px; border: 1px solid var(--line);
}
.post pre {
  background: var(--ink); color: #e6edf7; padding: 16px 18px;
  overflow-x: auto; border-left: 3px solid var(--copper);
}
.post pre code { background: none; border: 0; color: inherit; padding: 0; }
.post blockquote {
  margin: 0 0 16px; padding: 10px 18px; border-left: 3px solid var(--copper-l);
  background: var(--bg-soft); color: var(--ink);
}
.post table { border-collapse: collapse; width: 100%; margin: 0 0 18px; font-size: 15px; }
.post th, .post td { border: 1px solid var(--line); padding: 8px 11px; text-align: left; }
.post th { background: var(--bg-soft); font-family: var(--mono); font-size: 12px; }
.post-tags { margin-top: 26px; }
.tag {
  display: inline-block; margin-right: 7px; padding: 4px 9px;
  font-family: var(--mono); font-size: 11px; letter-spacing: 0.06em;
  border: 1px solid var(--line); color: var(--muted);
}

/* --------------------------------------------------------------- support -
   The buttons are inert until the accounts exist. A support button that
   404s is worse than no support button, so an unset one says so. */
.funds { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
.fund { border: 1px solid var(--line); padding: 22px 20px; background: var(--card); }
.fund h2 { margin: 0 0 8px; font-size: 18px; }
.fund p { margin: 0 0 16px; color: var(--muted); font-size: 14.5px; }
.btn-off { opacity: .5; pointer-events: none; }
.elsewhere { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; margin-top: 22px; }
.elsew { border-top: 2px solid var(--ink); padding-top: 14px; }
.elsew h3 { margin: 0 0 7px; font-size: 17px; }
.elsew p { margin: 0 0 10px; color: var(--muted); font-size: 14.5px; }
@media (max-width: 860px) {
  .funds, .elsewhere { grid-template-columns: 1fr; }
}


/* ---------------------------------------------------------- walkthrough -
   A numbered sequence for an engineer who has never opened the application:
   what to click, what happens, and why it matters. Only ever built from real
   captures taken in order - there is no staged walkthrough on this site. */
.howto { background: var(--bg-soft); }
.steps-list { list-style: none; margin: 30px 0 0; padding: 0; counter-reset: s; }
.step-card {
  display: grid; grid-template-columns: 340px 1fr; gap: 30px;
  align-items: start; padding: 28px 0; border-top: 1px solid var(--line);
}
.step-card:last-child { border-bottom: 1px solid var(--line); }
.step-text { position: relative; }
.step-n {
  display: inline-block; min-width: 30px; padding: 3px 0;
  margin-bottom: 10px; text-align: center;
  font-family: var(--mono); font-size: 13px; font-weight: 700;
  color: #fff; background: var(--navy);
}
.step-text h3 { margin: 0 0 8px; font-size: 19px; letter-spacing: -0.01em; }
.step-text p { margin: 0; font-size: 15px; color: var(--ink); line-height: 1.7; }
.step-card .shot { margin: 0; }
.step-card .shot img { border: 1px solid var(--line); }
@media (max-width: 900px) {
  .step-card { grid-template-columns: 1fr; gap: 18px; }
}


/* ------------------------------------------------------------- hardware -
   A board gets a state pill the way an application gets a status pill, and
   for the same reason: nothing here is fabricated, and the page says so. */
.hw { padding-bottom: 0; }
.hw-head {
  display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap;
  padding-bottom: 12px; border-bottom: 2px solid var(--ink); margin-bottom: 16px;
}
.hw-head h2 { margin: 0; font-size: 26px; letter-spacing: -0.02em; }
.hw-sub {
  font-family: var(--mono); font-size: 12px; letter-spacing: 0.06em;
  color: var(--muted); text-transform: none;
}
.hw-tagline { margin: 0 0 20px; font-size: 18px; color: var(--navy); }
.hw-nav { display: flex; flex-wrap: wrap; gap: 10px; }
.hw-nav a {
  font-family: var(--mono); font-size: 12px; letter-spacing: 0.04em;
  padding: 7px 12px; border: 1px solid var(--line); background: var(--card);
  color: var(--ink); text-decoration: none;
}
.hw-nav a:hover { border-color: var(--copper); color: var(--copper); }

.specs { align-self: start; border-top: 1px solid var(--line); }
.spec {
  display: flex; gap: 14px; padding: 9px 0;
  border-bottom: 1px solid var(--line); font-size: 14.5px;
}
.spec .k {
  flex: 0 0 34%; font-family: var(--mono); font-size: 11.5px;
  letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted);
  padding-top: 2px;
}
.spec .v { flex: 1; }
.encl {
  margin-top: 16px; padding: 12px 14px; background: var(--bg-soft);
  border-left: 3px solid var(--copper-l); font-size: 14.5px;
}
.encl b {
  display: block; margin-bottom: 3px; font-family: var(--mono);
  font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--copper);
}
.pill-designed { border-color: var(--muted); color: var(--muted); }
.pill-fabricated, .pill-built { border-color: var(--navy); color: var(--navy); }

/* ----------------------------------------------------------------- about -
   The portrait sits beside the text on a wide screen and above it on a
   narrow one. Its caption says the photograph was tidied up, because the
   rest of this site refuses to show anything it has not labelled. */
.about-grid {
  display: grid; grid-template-columns: 320px 1fr; gap: 40px;
  align-items: start;
}
.portrait { margin: 0; }
.portrait img {
  display: block; width: 100%; height: auto;
  border: 1px solid var(--line);
}
.portrait figcaption {
  margin-top: 10px; font-family: var(--mono); font-size: 11.5px;
  line-height: 1.6; color: var(--muted);
}
@media (max-width: 820px) {
  .about-grid { grid-template-columns: 1fr; gap: 26px; }
  .portrait { max-width: 300px; }
}


/* ------------------------------------------------------- protocol matrix -
   Which application speaks what, in and out. Colour carries direction, but
   the cell text says it too, so it does not depend on seeing colour. */
.proto-wrap { overflow-x: auto; border: 1px solid var(--line); }
.proto { border-collapse: collapse; width: 100%; min-width: 760px; font-size: 14px; }
.proto th, .proto td {
  border: 1px solid var(--line); padding: 10px 12px; text-align: left;
}
.proto thead th {
  background: var(--ink); color: #fff; font-family: var(--mono);
  font-size: 11.5px; letter-spacing: 0.08em; text-transform: uppercase;
}
.proto tbody th { background: var(--bg-soft); font-weight: 600; white-space: nowrap; }
.proto tbody th a { color: var(--ink); text-decoration: none; }
.proto tbody th a:hover { color: var(--copper); }
.proto td { font-family: var(--mono); font-size: 12.5px; }
.p-no   { color: #cbd5e1; }
.p-inn  { background: #eef4ff; color: var(--navy); }
.p-out  { background: #fff7ed; color: var(--copper); }
.p-both { background: #ecfdf5; color: #047857; font-weight: 600; }

/* the worked chain */
.chain { list-style: none; margin: 26px 0 0; padding: 0; }
.chain-step {
  display: grid; grid-template-columns: 54px 1fr; gap: 18px;
  padding: 20px 0; border-top: 1px solid var(--line);
}
.chain-step:last-child { border-bottom: 1px solid var(--line); }
.chain-step h3 { margin: 0 0 5px; font-size: 18px; }
.chain-step p { margin: 0; color: var(--muted); font-size: 15px; line-height: 1.65; }
.chain-step p + p { margin-top: 10px; }
.chain-step .step-n { align-self: start; }
.chain-step .sys-apps {
  font-family: var(--mono); font-size: 13px; letter-spacing: -0.01em;
}
.chain-step .sys-apps a { color: var(--copper); }


/* ------------------------------------------------------------- pillars -
   The four things this practice makes, on the home page. A card that is a
   whole link, so the entire tile is the target rather than a word in it. */
.pillar {
  position: relative; display: block; padding: 26px 24px 22px;
  border: 1px solid var(--line); background: var(--card);
  text-decoration: none; color: inherit;
  transition: border-color .18s ease, transform .18s ease;
}
.pillar::before, .pillar::after {
  content: ""; position: absolute; width: 8px; height: 8px;
  border-color: var(--copper-l); border-style: solid; opacity: .75;
}
.pillar::before { top: 7px; left: 7px; border-width: 1px 0 0 1px; }
.pillar::after { bottom: 7px; right: 7px; border-width: 0 1px 1px 0; }
.pillar:hover { border-color: var(--copper); transform: translateY(-2px); }
.pillar .num {
  display: block; margin-bottom: 10px;
  font-family: var(--mono); font-size: 12px; letter-spacing: 0.1em;
  color: var(--copper);
}
.pillar h3 { margin: 0 0 9px; font-size: 20px; letter-spacing: -0.02em; }
.pillar p { margin: 0 0 14px; color: var(--muted); font-size: 15px; line-height: 1.65; }
.pillar-go {
  font-family: var(--mono); font-size: 11.5px; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--navy);
}
.pillar:hover .pillar-go { color: var(--copper); }
.cap.span2 { grid-column: 1 / -1; }


/* ------------------------------------------------------- category heads -
   The catalogue is split the way the practice is: software an engineer runs
   to design and analyse, and software that behaves like bench equipment.
   The heading carries the split so a visitor does not have to infer it. */
.cat-head {
  margin: 54px 0 22px; padding-bottom: 14px;
  border-bottom: 2px solid var(--ink);
}
.cat-head:first-child { margin-top: 0; }
.cat-head h2 { margin: 0 0 6px; font-size: 26px; letter-spacing: -0.02em; }
.cat-head p { margin: 0; color: var(--muted); max-width: 62ch; font-size: 15px; }

/* the same split, on the hand-written home page */
.tools-head {
  margin: 30px 0 12px;
  font-family: var(--mono); font-size: 11.5px; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--navy);
}
.tools-head:first-of-type { margin-top: 0; }

/* --------------------------------------------------------------- caveat -
   What an application does not do, or has not been tried, stated on its own
   page. An engineer who finds the limit himself stops believing the rest. */
.caveat-band { padding: 0; background: var(--bg-soft); }
.caveat-band .wrap { padding-top: 26px; padding-bottom: 26px; }
.caveat {
  margin: 0; padding: 16px 20px; background: var(--card);
  border: 1px solid var(--line); border-left: 3px solid var(--copper);
  font-size: 15px; line-height: 1.65; color: var(--ink);
}
.caveat strong { font-weight: 650; color: var(--ink); }
.caveat b {
  display: block; margin-bottom: 5px;
  font-family: var(--mono); font-size: 11px; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--copper);
}


/* ------------------------------------------------------------- task panes -
   An Excel task pane is taller than it is wide. Stretching one to the width of
   the text column blows a 486px capture up to 1080px and turns crisp UI into
   mush, so a band of nothing but portrait captures shows them at their own
   size, side by side, and stacks them on a narrow screen. */
/* A single tall capture inside an otherwise normal band: cap it at its own
   width and centre it, rather than blowing a 486px pane up to the full
   1080px column. Applies whether or not the band is a .panes band. */
.shot.portrait { max-width: 470px; margin-inline: auto; }

.shot-band.panes .wrap {
  display: flex; flex-wrap: wrap; gap: 26px; justify-content: center;
}
.shot-band.panes .shot { flex: 0 1 486px; max-width: 486px; }
.shot-band.panes .shot + .shot { margin-top: 0; }
@media (max-width: 720px) {
  .shot-band.panes .shot { flex-basis: 100%; max-width: 100%; }
}


/* ------------------------------------------------------ diagram, full width -
   A drawn diagram carries its meaning in its labels, so it gets the whole
   viewport instead of the 1080px text column a screenshot lives in. */
.shot-band.diagram .wrap { max-width: 1680px; padding-inline: 28px; }
.shot-band.diagram .shot { padding: 0; border: 0; background: transparent; }
.shot-band.diagram .shot img {
  border: 1px solid rgba(245, 158, 11, 0.3);
}
.shot-band.diagram figcaption {
  max-width: 96ch; margin-inline: auto; text-align: center;
  font-size: 13px; padding-top: 16px;
}
@media (max-width: 720px) {
  .shot-band.diagram .wrap { padding-inline: 16px; }
}

/* Images declare their intrinsic size; keep them fluid but keep the ratio. */
.shot img { height: auto; }

/* A dense diagram squeezed to 343px is unreadable. Below 900px it keeps a
   legible width and pans sideways instead. */
@media (max-width: 900px) {
  .shot-band.diagram .shot {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: thin;
  }
  .shot-band.diagram .shot img { min-width: 860px; width: 860px; }
  .shot-band.diagram figcaption::after {
    content: " (scroll the diagram sideways to read it)";
    color: var(--copper-l);
  }
}

/* The tools grid is generated, so its length changes. A lone last cell
   spans both columns rather than leaving a hole. */
.tools .tool { display: block; text-decoration: none; color: inherit;
               transition: background .15s; }
.tools .tool:hover { background: var(--bg-soft); }
.tools .tool.span2 { grid-column: 1 / -1; border-right: 0; }
.tools .tool:nth-last-child(-n+2) { border-bottom: 0; }
.tools .tool.span2:nth-last-child(2) { border-bottom: 1px solid var(--line); }


/* ------------------------------------------------------- with / without -
   The comparison table on effort.html. The left column is reasoning and the
   right column is measured output, so they are coloured differently on
   purpose - nobody should be able to read the two as the same kind of
   claim. */
.vs-wrap { overflow-x: auto; border: 1px solid var(--line); }
.vs { border-collapse: collapse; width: 100%; min-width: 880px; }
.vs th, .vs td {
  border: 1px solid var(--line); padding: 14px 16px;
  text-align: left; vertical-align: top;
  font-size: 14.5px; line-height: 1.6;
}
.vs thead th {
  background: var(--ink); color: #fff; font-family: var(--mono);
  font-size: 11.5px; letter-spacing: 0.08em; text-transform: uppercase;
  white-space: nowrap;
}
.vs tbody th {
  width: 23%; background: var(--bg-soft); font-weight: 600;
  color: var(--ink);
}
.vs-no  { width: 35%; color: var(--muted-2); background: #fdfaf6; }
.vs-yes { width: 42%; color: var(--ink); background: #f6fbf8; }
.vs-yes a { font-family: var(--mono); text-decoration: none; color: var(--copper); }
.vs-yes a:hover { color: var(--ink); }

/* -------------------------------------------------------- being built -
   Not products. No screenshots, no download, no price - the card is
   deliberately plainer than a .tool so it cannot be mistaken for one. */
.soon-grid {
  /* Four entries, so two by two rather than three and a widow. */
  display: grid; grid-template-columns: repeat(2, 1fr);
  gap: 1px; background: var(--line);
  border: 1px solid var(--line); margin-top: 26px;
}
.soon { background: var(--card); padding: 24px 22px; }
.soon h3 {
  margin: 6px 0 4px; font-size: 19px; line-height: 1.3;
  display: flex; flex-direction: column; gap: 7px;
}
.soon-state {
  align-self: flex-start;
  font-family: var(--mono); font-size: 10.5px; font-weight: 600;
  letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--copper); background: #fff7ed;
  border: 1px solid #fed7aa; padding: 3px 9px;
}
.soon-tag { margin: 0 0 14px; font-size: 15px; color: var(--ink); }
.soon p { font-size: 14px; line-height: 1.65; color: var(--muted); margin: 0 0 12px; }
.soon p:last-child { margin-bottom: 0; }
.soon p b {
  font-family: var(--mono); font-size: 11px; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--muted-2);
}

@media (max-width: 860px) {
  .soon-grid { grid-template-columns: 1fr; }
}

/* On a phone the 1200px sheet crops to one dense corner, so shrink it. */
@media (max-width: 860px) {
  section.soft::before { background-size: 680px 510px; }
  section.soft:nth-of-type(even)::before { background-position: 180px -90px; }
}


/* ------------------------------------------------- instrument readout -
   The look is borrowed from a mock-up: a dark monitor panel with a cyan
   edge, scanlines across it, a mono micro-label over a large value. The
   numbers are not borrowed - the mock-up's were invented, and the whole
   point of a readout is that it is reading something. Every figure here
   is counted at build time by write_home_readout(), including the last
   one, which is measured by scanning the pages the build just wrote. */
.readout {
  display: grid; grid-template-columns: repeat(4, 1fr);
  margin: 34px 0 24px; position: relative; overflow: hidden;
  border: 1px solid rgba(103, 232, 249, 0.24);
  background: rgba(15, 23, 42, 0.55);
}
.readout::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(rgba(0,0,0,0) 50%, rgba(0,0,0,0.17) 50%);
  background-size: 100% 4px;
}
.ro {
  padding: 17px 20px 15px;
  border-right: 1px solid rgba(103, 232, 249, 0.14);
}
.ro:last-child { border-right: 0; }
.ro-k {
  display: block; font-family: var(--mono);
  font-size: 10.5px; font-weight: 600; letter-spacing: 0.16em;
  text-transform: uppercase; color: rgba(226, 232, 240, 0.52);
}
.ro-v {
  display: block; font-family: var(--mono); font-size: 32px;
  font-weight: 700; line-height: 1.05; margin: 7px 0 5px;
  color: #67e8f9; letter-spacing: -0.02em;
}
.ro-zero .ro-v { color: #2dd4bf; }
.ro-s {
  font-family: var(--mono); font-size: 11px; line-height: 1.45;
  color: rgba(226, 232, 240, 0.44);
}

/* a cyan wash behind the hero, so the panel sits in light rather than on it */
.hero::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(ellipse 70% 60% at 28% 42%,
              rgba(6, 182, 212, 0.10) 0%, transparent 70%);
}

/* a card lifts under the cursor instead of only changing its line */
:is(.card, .pillar, .soon, .fund, .app-card, .form-card):hover {
  border-color: var(--copper);
  box-shadow: 0 0 0 1px rgba(171, 77, 8, 0.10),
              0 10px 30px rgba(30, 58, 138, 0.09);
}
:is(.card, .soon, .fund, .form-card) {
  transition: border-color .18s ease, box-shadow .18s ease;
}

/* the scrollbar in the same palette, rather than the browser's grey */
::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: var(--bg-soft); }
::-webkit-scrollbar-thumb {
  background: #b7c7dc; border: 3px solid var(--bg-soft); border-radius: 7px;
}
::-webkit-scrollbar-thumb:hover { background: var(--copper); }

@media (max-width: 900px) {
  .readout { grid-template-columns: repeat(2, 1fr); }
  .ro:nth-child(2n) { border-right: 0; }
  .ro:nth-child(-n+2) { border-bottom: 1px solid rgba(103, 232, 249, 0.14); }
}
@media (max-width: 520px) {
  .readout { grid-template-columns: 1fr; }
  .ro { border-right: 0; border-bottom: 1px solid rgba(103, 232, 249, 0.14); }
  .ro:last-child { border-bottom: 0; }
  .ro-v { font-size: 27px; }
}


/* ------------------------------------------------------------ downloads -
   One row per build. The hash is the point of the table, so it gets a
   line of its own rather than being truncated into a tooltip nobody
   opens - a hash you cannot read is a hash you cannot check. */
.dl-wrap { overflow-x: auto; border: 1px solid var(--line); }
.dl { border-collapse: collapse; width: 100%; min-width: 940px; }
.dl th, .dl td {
  border: 1px solid var(--line); padding: 13px 15px;
  text-align: left; vertical-align: top; font-size: 14.5px;
}
.dl thead th {
  background: var(--ink); color: #fff; font-family: var(--mono);
  font-size: 11.5px; letter-spacing: 0.08em; text-transform: uppercase;
  white-space: nowrap;
}
.dl tbody th { background: var(--bg-soft); font-weight: 600; width: 20%; }
.dl tbody th a { color: var(--ink); text-decoration: none; }
.dl tbody th a:hover { color: var(--copper); }
.dl-cli {
  display: block; margin-top: 3px;
  font-family: var(--mono); font-size: 11.5px; color: var(--muted);
}
.dl-file code { font-size: 12.5px; word-break: break-all; }
.dl-sha {
  display: block; margin-top: 6px;
  font-family: var(--mono); font-size: 10.5px; line-height: 1.5;
  color: var(--muted); word-break: break-all;
}
.dl-size { white-space: nowrap; font-family: var(--mono); font-size: 13px; }
.dl-act { white-space: nowrap; }

/* The State column holds one pill - AVAILABLE 1.4.2, EARLY RELEASE 0.1.1 - and
   at this letter-spacing it wrapped to three lines in a column sized for the
   widest of the others. The table already scrolls inside .dl-wrap and carries a
   min-width, so letting this column take the width it needs costs nothing. */
.dl tbody td:last-child {
  white-space: nowrap; width: 1%;
}
.dl-btn { padding: 9px 18px; font-size: 12px; }
.dl-pending {
  display: block; max-width: 20ch;
  /* .dl-act is nowrap so its button cannot break. That inherits, and
     this text is a sentence: without this it ignores the max-width
     above and runs across the State column. */
  white-space: normal;
  font-family: var(--mono); font-size: 11.5px; line-height: 1.55;
  color: var(--muted);
}
.dl-none th, .dl-none td { background: var(--bg-soft2); }
.dl-note { color: var(--muted-2); font-size: 14px; }


/* ---------------------------------------------------------- brand film -
   The two logo animations, served from this site. Muted, looping and
   without controls, because a logo reveal is not something anyone wants
   to scrub through. There is no JavaScript here to pause them, so the
   still sits in the markup beside the video and CSS swaps the two over
   when the reader has asked for reduced motion. */
.brandband .wrap { padding-top: 40px; padding-bottom: 40px; }
.brandfilm {
  margin: 0; border: 1px solid rgba(103, 232, 249, 0.22);
  background: #0b111d; padding: 10px;
}
.brandfilm video, .brandfilm img {
  display: block; width: 100%; height: auto;
  border: 1px solid rgba(255, 255, 255, 0.08);
}
.brandfilm figcaption {
  margin-top: 12px; padding: 0 4px 2px;
  font-family: var(--mono); font-size: 12px; line-height: 1.6;
  color: rgba(255, 255, 255, 0.62);
}
/* These need to out-specify ".brandfilm video, .brandfilm img" above, or
   the still renders underneath the video and the band shows it twice. */
.brandfilm .bf-still { display: none; }
@media (prefers-reduced-motion: reduce) {
  .brandfilm .bf-motion { display: none; }
  .brandfilm .bf-still  { display: block; }
}

/* The roadmap gallery sits on a dark band, so its label needs the light
   copper rather than the one tuned for paper. */
.shot-band .eyebrow-dark { color: var(--copper-l); }
.shot-band .shot + .shot { margin-top: 26px; }

/* ----------------------------------------------------------------- clips -
   Recordings of an application running. Posters only until pressed, two up
   on a wide screen and one up on a narrow one. */
.clips { display: grid; grid-template-columns: repeat(2, 1fr); gap: 26px; }
.clip { margin: 0; }
.clip video {
  display: block; width: 100%; height: auto; background: var(--ink);
  border: 1px solid var(--line);
}
.clip figcaption {
  margin-top: 10px; font-size: 14px; line-height: 1.6; color: var(--muted);
}
.clip figcaption b {
  font-family: var(--mono); font-size: 12px; color: var(--copper);
  margin-right: 8px;
}
.clips-one { grid-template-columns: minmax(0, 860px); justify-content: center; }
@media (max-width: 860px) { .clips { grid-template-columns: 1fr; } }

/* ------------------------------------------------------------ file list -
   The published run, group by group. Every file the publish wrote appears
   here, so the list has to stay readable at a hundred-odd entries. */
.fgroups { display: grid; gap: 34px; }
.fgroup h3 {
  margin: 0 0 6px; font-size: 18px; display: flex; align-items: baseline;
  gap: 10px;
}
.fcount {
  font-family: var(--mono); font-size: 12px; font-weight: 600;
  color: #fff; background: var(--navy); padding: 2px 8px;
}
.fgroup > p { margin: 0 0 14px; color: var(--muted); max-width: 70ch; }
.files {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(290px, 1fr));
  gap: 2px 26px;
}
.files li {
  display: flex; justify-content: space-between; gap: 14px;
  padding: 7px 0; border-bottom: 1px solid var(--line); font-size: 14px;
}
/* The report file list names files without linking to them: the run is
   described, not published. Same metrics as the link it replaced. */
.files a, .f-name { font-family: var(--mono); font-size: 13px; word-break: break-all; }
.f-meta {
  font-family: var(--mono); font-size: 11.5px; color: var(--muted);
  white-space: nowrap; padding-top: 1px;
}
.vs td.num, .vs th.num { text-align: right; }

/* The mechanical gallery. The renders are transparent PNGs on a square canvas,
   so they need a surface to sit on and room around them rather than a frame
   tight to the pixels. No captions by design - see _site_source/mechanical.py. */
.cad-grid {
  display: grid; gap: 14px;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
}
.cad-grid img {
  width: 100%; height: auto; aspect-ratio: 1; object-fit: contain;
  background: var(--bg-soft); border: 1px solid var(--line);
  padding: 10px; display: block;
}
@media (max-width: 560px) {
  .cad-grid { grid-template-columns: repeat(auto-fill, minmax(118px, 1fr)); gap: 10px; }
}

/* ---------------------------------------------------------------- on the dark
   The five dark grounds are .hero, .app-hero, .shot-band, .contact-panel and
   .app-card.hub. Anything inside them that would otherwise take a colour chosen
   for paper is lifted to --sky. Scoped rather than changing --muted-2 itself,
   because that colour is correct everywhere else - on paper it measures 8.35:1,
   and turning it light would make every other page unreadable instead. */
.hero .sub, .app-hero .sub, .shot-band .sub,
.contact-panel .sub, .app-card.hub .sub,
.hero .two-col > div > p, .app-hero .two-col > div > p,
.shot-band .two-col > div > p {
  color: var(--sky);
}

/* Links on the dark, which were --navy on --ink at 1.77:1. They stay
   underlined, so the colour is not the only thing saying they are links.

   Written as one rule over all five dark grounds rather than per container.
   The first attempt named .sub and figcaption, then .app-status when the
   measurement found one there, and would have gone on finding another - the
   colour depends on the ground, not on which element happens to sit on it. */
.hero a:not(.btn):not(.cta):not(.btn-ghost):not(.btn-outline):not(.brand),
.app-hero a:not(.btn):not(.cta):not(.btn-ghost):not(.btn-outline):not(.brand),
.shot-band a:not(.btn):not(.cta):not(.btn-ghost):not(.btn-outline):not(.brand),
.contact-panel a:not(.btn):not(.cta):not(.btn-ghost):not(.btn-outline):not(.brand),
.app-card.hub a:not(.btn):not(.cta):not(.btn-ghost):not(.btn-outline):not(.brand) {
  color: var(--sky);
}

/* Two more that the scoped rules above did not reach, both found by measuring
   rather than by looking: a link in .app-status sits on the dark hero, and a
   pill inside .app-card.hub sits on a dark card. */
/* The existing pill colours assume "not .app-hero" means paper. It does not:
   .app-card.hub, .shot-band and .contact-panel are dark too, and --copper on
   --ink measures 2.68:1. --copper-l is the same accent chosen for dark ground
   and measures 8.52:1. */
.app-card.hub .pill-early, .shot-band .pill-early, .contact-panel .pill-early {
  color: var(--copper-l);
}
.app-card.hub .pill-shipping, .shot-band .pill-shipping, .contact-panel .pill-shipping {
  color: #34d399;
}
.app-card.hub .pill-dev, .shot-band .pill-dev, .contact-panel .pill-dev {
  color: #94a3b8;
}

/* .portrait figcaption sets --muted, which is right for a portrait figure on
   paper and wrong for one inside .shot - that carries its own #0b111d ground,
   and the caption measured 2.66:1 there. .shot figcaption already sets the
   light colour; this only has to win back the override. .shot-light is the
   deliberate paper variant and keeps --muted. */
.shot:not(.shot-light).portrait figcaption {
  color: rgba(255, 255, 255, 0.62);
}
