/* subscribe.css — the pricing page, and the only stylesheet it loads.
 *
 * WHY NOT app.css
 *
 * app.css is 236 KB: the whole terminal, its grid, its story rail, its charts.
 * Every other page pays that because every other page IS the terminal. This
 * one is the commercial front door — the first thing a stranger loads, on a
 * phone, from a link — and 236 KB of terminal CSS to draw three cards is the
 * kind of cost that shows up as a bounce, not as a bug.
 *
 * THE TOKENS BELOW ARE A MIRROR, NOT A FORK. They are copied from app.css's
 * :root and [data-theme="light"] blocks so this page is the same product to
 * look at. A copy can drift, so build/test_subscribe.py parses BOTH files and
 * fails if any mirrored value stops matching. Change a colour in app.css and
 * that test tells you this file needs the same edit — which is the whole
 * reason the mirror is allowed to exist.
 */

/* --sans MIRRORS app.css EXACTLY (build/test_subscribe.py holds it to that),
   so the symbol face is not in the stack; it is applied to the one control
   that draws the glyph, below. */
/* theme.js writes ◑ / ◐ (U+25D1 / U+25D0) into the theme button. Those live in
   the self-hosted Noto subset, and this page does not load app.css where the
   face is declared — so without this the glyph falls back to whatever the
   system has, which is exactly the trap assets/fonts/README.md documents. */
@font-face {
  font-family: "AXIOM Symbols";
  src: url("fonts/sym-inter.woff2") format("woff2");
  font-display: swap;
  unicode-range: U+2190, U+2192, U+2197, U+21B3, U+2298, U+25A0, U+25B2,
                 U+25B6, U+25BC, U+25C6, U+2605, U+2606, U+2665, U+2713;
}
@font-face {
  font-family: "AXIOM Symbols";
  src: url("fonts/sym-noto.woff2") format("woff2");
  font-display: swap;
  unicode-range: U+25B4, U+25B8, U+25BE, U+25D0, U+25D1, U+26A1, U+2715, U+270D;
}
@font-face {
  font-family: "AXIOM Symbols";
  src: url("fonts/sym-math.woff2") format("woff2");
  font-display: swap;
  unicode-range: U+21C4, U+21F1, U+2261;
}

:root {
  --bg:        #0A2032;
  --bg2:       #081B2B;
  --panel:     #0E2A3D;
  --panel2:    #13314A;
  --field:     #163952;
  --grid:      #1B374F;
  --grid-soft: #163045;
  --text:      #E9F1F8;
  --text-dim:  #A9BDCD;
  --faint:     #7A93A6;
  --brand:     #4D9BE0;
  --brand-l:   #5BA6E8;
  --brand-d:   #1D6BB4;
  --cont:      #D8944A;
  --up:        #1f9d6b;
  --up-l:      #3ec78f;
  --save-fg:   #3ec78f;   /* page-local, see .save */
  --footer:    #071521;
  --mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --sans: "Inter", "AXIOM Symbols", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --serif: "Newsreader", Georgia, "Times New Roman", serif;
}

[data-theme="light"] {
  --bg:        #FFFFFF;
  --bg2:       #F2F5F8;
  --panel:     #F2F5F8;
  --panel2:    #E6F1FB;
  --field:     #FFFFFF;
  --grid:      #D8E0E8;
  --grid-soft: #E9EEF3;
  --text:      #0A2032;
  --text-dim:  #5B6B7A;
  --faint:     #547392;
  --brand:     #2F6FAE;
  --brand-l:   #2F6FAE;
  --brand-d:   #1D6BB4;
  --cont:      #B06A1E;
  --up:        #1f9d6b;
  --up-l:      #178a5d;
  --save-fg:   #16865a;   /* page-local, see .save */
  --footer:    #F2F5F8;
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}
a { color: var(--brand); }
img { max-width: 100%; }

/* Focus is never removed, only restyled. Half this page is keyboard-operable
   controls (a toggle, eight CTAs, nine FAQ rows) and an invisible focus ring
   makes all of it unusable without a mouse. */
:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 3px;
  border-radius: 4px;
}

.wrap { max-width: 1120px; margin: 0 auto; padding: 0 24px; }

/* ---- top bar ------------------------------------------------------------ */
.nav {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; padding: 20px 0 8px;
}
.nav-mark {
  font-family: var(--mono); font-size: 11px; font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase; color: var(--text);
  text-decoration: none; line-height: 1.3;
}
.nav-mark span { color: var(--brand); }
.nav-right { display: flex; align-items: center; gap: 8px; }
.nav-a {
  font-size: 13.5px; color: var(--text-dim); text-decoration: none;
  padding: 8px 12px; border-radius: 8px;
}
.nav-a:hover { color: var(--text); background: var(--panel); }
.nav-btn {
  font: inherit; font-size: 13.5px; cursor: pointer;
  padding: 8px 12px; border-radius: 8px;
  border: 1px solid var(--grid); background: transparent; color: var(--text-dim);
}
.nav-btn:hover { color: var(--text); border-color: var(--faint); }

/* ---- hero --------------------------------------------------------------- */
.hero { text-align: center; padding: 56px 0 8px; }
.eyebrow {
  font-family: var(--mono); font-size: 11px; letter-spacing: .18em;
  text-transform: uppercase; color: var(--faint); margin: 0 0 18px;
}
.h1 {
  font-family: var(--serif); font-weight: 600;
  font-size: clamp(34px, 6.2vw, 58px); line-height: 1.08;
  letter-spacing: -.02em; margin: 0 0 18px;
}
.lede {
  font-size: clamp(16px, 2.1vw, 19px); color: var(--text-dim);
  max-width: 42ch; margin: 0 auto; line-height: 1.5;
}
.lede b { color: var(--text); font-weight: 600; }
/* ?from=deals|universe: the one line that says why they are here */
.from-note {
  font-family: var(--mono); font-size: 12px; letter-spacing: .03em; line-height: 1.5;
  color: var(--text); background: var(--panel2); border: 1px solid var(--grid);
  border-radius: 10px; padding: 10px 14px; max-width: 62ch; margin: 18px auto 0;
}
.from-note[hidden] { display: none; }

/* ---- hero sub ----------------------------------------------------------- */
/* The segmented monthly/annual control that used to sit here is gone: with
   Monthly and Annual as their own cards, a toggle would have been a second way
   to ask a question the cards already answer — and it hid the annual saving
   behind a click instead of standing it next to the monthly price. */
.hero-sub {
  text-align: center; font-size: 13px; color: var(--faint);
  margin: 16px auto 30px; max-width: 46ch;
}

/* ---- plan cards --------------------------------------------------------- */
.plans {
  display: grid; gap: 18px; padding: 4px 0 8px;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  align-items: start;
}
/* FIVE ACROSS needs more room than the 1120px the prose is set at, so the
   pricing block alone breaks out to 1320. Cards narrower than ~230px turn
   every bullet into four lines and the row stops being scannable, which is
   the only job it has. Detail lives in the comparison table below. */
/* The breakout itself, shared: Enterprise Plus sits directly under the row and
   has to line up with it. Measured before this was factored out — the cards
   ran to 1320 and the band stopped at 1072, so the tier that is meant to read
   as the widest one was visibly the narrowest thing on the screen. */
.plans--four, .eplus {
  max-width: 1320px; width: calc(100vw - 48px);
  margin-left: 50%; transform: translateX(-50%);
}
.plans--four {
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 16px;
}
.plans--four .plan { padding: 22px 18px 20px; border-radius: 14px; }
.plans--four .plan-num { font-size: 32px; }
.plans--four .plan-num.is-word { font-size: 21px; }
.plans--four .plan-for { font-size: 13px; min-height: 54px; }
.plans--four .plan-list li { font-size: 13.5px; }
.plans--four .plan-cta { font-size: 13.5px; padding: 11px 12px; }
.plan {
  position: relative; display: flex; flex-direction: column;
  background: var(--bg); border: 1px solid var(--grid);
  border-radius: 16px; padding: 26px 24px 24px;
}
/* The recommended plan is the one being sold, so it is the one that looks
   sold: brand border, a tint, and it does not move on hover — a card that
   jumps under the cursor is a card you can miss when you click. */
.plan.is-pick {
  border-color: var(--brand); background: var(--panel);
  box-shadow: 0 0 0 1px var(--brand);
}
.plan-tag {
  position: absolute; top: -11px; left: 24px;
  font-family: var(--mono); font-size: 10px; font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase;
  color: #fff; background: var(--brand-d);
  padding: 4px 10px; border-radius: 999px;
}
.plan-name { font-size: 17px; font-weight: 700; margin: 0 0 4px; letter-spacing: -.01em; }
.plan-for { font-size: 13.5px; color: var(--text-dim); margin: 0 0 20px; min-height: 40px; }
.plan-cost { display: flex; align-items: baseline; gap: 7px; flex-wrap: wrap; }
.plan-num {
  font-family: var(--mono); font-size: 40px; font-weight: 600;
  letter-spacing: -.03em; line-height: 1;
}
/* A word in the price slot ("Free", "Let's talk") set at the numeric size
   out-shouts £15, which is the one number on the page that has to win. */
.plan-num.is-word { font-size: 27px; letter-spacing: -.01em; }
.plan-per { font-size: 13.5px; color: var(--text-dim); }
.plan-fx {
  font-family: var(--mono); font-size: 12px; color: var(--faint);
  margin: 9px 0 0; min-height: 18px;
}
.plan-bill { font-size: 12.5px; color: var(--text-dim); margin: 5px 0 0; min-height: 19px; }
.plan-cta {
  display: block; width: 100%; margin: 20px 0 18px; text-align: center;
  font: inherit; font-size: 14.5px; font-weight: 600; cursor: pointer;
  padding: 12px 16px; border-radius: 10px; text-decoration: none;
  border: 1px solid var(--grid); background: var(--bg); color: var(--text);
  transition: filter .16s ease, border-color .16s ease;
}
.plan-cta:hover { border-color: var(--faint); }
.plan-cta.is-primary {
  background: var(--brand-d); border-color: var(--brand-d); color: #fff;
}
.plan-cta.is-primary:hover { filter: brightness(1.1); }
.plan-note {
  font-size: 12px; color: var(--faint); text-align: center;
  margin: -12px 0 16px; min-height: 17px;
}
.plan-inc {
  font-family: var(--mono); font-size: 10.5px; font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase; color: var(--faint);
  margin: 0 0 11px; padding-top: 16px; border-top: 1px solid var(--grid-soft);
}
.plan-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 9px; }
/* NOT display:grid, and this cost a rebuild to notice. Under grid, every
   child of the li becomes a grid item — and so does every run of bare text
   between them. A bullet reading "The <b>ledger</b> — all <span>247</span>
   rows" is five items, not one, so a two-column track laid them out three
   rows deep and each bullet stood 117–228px tall instead of 20. Position the
   tick out of flow instead and the text stays ordinary inline text. */
.plan-list li {
  position: relative; padding-left: 26px;
  font-size: 14px; line-height: 1.42; color: var(--text-dim);
}
.plan-list b { color: var(--text); font-weight: 600; }
/* The tick is drawn, not typed. A "✓" depends on a glyph the font may not
   have — the same unicode-range trap the wire already paid for once. */
.plan-list li::before {
  content: ""; position: absolute; left: 3px; top: 6px;
  width: 11px; height: 6px;
  border-left: 2px solid var(--up); border-bottom: 2px solid var(--up);
  transform: rotate(-45deg);
}

/* ---- numbers band ------------------------------------------------------- */
.band {
  margin: 46px 0 0; padding: 26px 24px;
  background: var(--panel); border: 1px solid var(--grid); border-radius: 16px;
  display: grid; gap: 18px; grid-template-columns: repeat(3, minmax(0, 1fr));
  text-align: center;
}
.band div b {
  display: block; font-family: var(--mono); font-size: 27px; font-weight: 600;
  letter-spacing: -.02em; color: var(--text);
}
.band div span { font-size: 13px; color: var(--text-dim); }

/* ---- section furniture -------------------------------------------------- */
.sec { padding: 62px 0 0; }
.sec-h {
  font-family: var(--serif); font-weight: 600;
  font-size: clamp(24px, 3.4vw, 33px); letter-spacing: -.015em;
  margin: 0 0 8px; text-align: center;
}
.sec-p {
  font-size: 15px; color: var(--text-dim); text-align: center;
  max-width: 56ch; margin: 0 auto 26px;
}

/* ---- comparison table --------------------------------------------------- */
/* Wide content scrolls inside its own box; the page body never scrolls
   sideways, which on a phone is the difference between a table and a mess. */
.cmp-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.cmp {
  width: 100%; min-width: 640px; border-collapse: collapse;
  font-size: 14px;
}
.cmp caption { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
.cmp th, .cmp td { padding: 13px 14px; border-bottom: 1px solid var(--grid-soft); }
.cmp thead th {
  position: sticky; top: 0; background: var(--bg); z-index: 1;
  border-bottom: 1px solid var(--grid); text-align: center;
  font-size: 14px; font-weight: 700;
}
.cmp thead th:first-child { text-align: left; }
.cmp thead th small { display: block; font-weight: 500; font-size: 12px; color: var(--text-dim); }
.cmp tbody th {
  text-align: left; font-weight: 500; color: var(--text-dim);
  font-size: 14px;
}
.cmp tbody th b { color: var(--text); font-weight: 600; display: block; }
.cmp tbody th span { font-size: 12.5px; color: var(--faint); }
.cmp td { text-align: center; color: var(--text-dim); }
.cmp .grp th {
  font-family: var(--mono); font-size: 10.5px; font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase; color: var(--faint);
  padding-top: 26px; border-bottom-color: var(--grid);
}
.cmp .yes, .cmp .no { font-size: 0; }
.cmp .yes::after {
  content: ""; display: inline-block; width: 12px; height: 7px;
  border-left: 2px solid var(--up); border-bottom: 2px solid var(--up);
  transform: rotate(-45deg); vertical-align: middle;
}
/* Absence is a dash, not an empty cell: an empty cell reads as "we forgot to
   fill this in", and on a comparison table that is the wrong doubt to create. */
.cmp .no::after {
  content: ""; display: inline-block; width: 11px; height: 0;
  border-top: 2px solid var(--grid); vertical-align: middle;
}
.cmp .pick { background: var(--panel); }

/* ---- faq ---------------------------------------------------------------- */
.faq { max-width: 760px; margin: 0 auto; }
.faq details {
  border-bottom: 1px solid var(--grid-soft);
}
.faq summary {
  cursor: pointer; list-style: none; padding: 17px 34px 17px 2px;
  font-size: 15.5px; font-weight: 600; position: relative;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: ""; position: absolute; right: 6px; top: 24px;
  width: 9px; height: 9px; border-right: 2px solid var(--faint);
  border-bottom: 2px solid var(--faint); transform: rotate(45deg);
  transition: transform .18s ease;
}
.faq details[open] summary::after { transform: rotate(-135deg); top: 27px; }
.faq summary:hover { color: var(--brand); }
.faq-a {
  padding: 0 34px 19px 2px; margin: 0; font-size: 15px;
  color: var(--text-dim); max-width: 68ch;
}
.faq-a + .faq-a { padding-top: 12px; }

/* ---- closing ------------------------------------------------------------ */
.end {
  margin: 62px 0 0; padding: 44px 28px; text-align: center;
  background: var(--panel); border: 1px solid var(--grid); border-radius: 18px;
}
.end h2 { font-family: var(--serif); font-weight: 600; font-size: clamp(23px, 3.2vw, 31px); margin: 0 0 10px; letter-spacing: -.015em; }
.end p { color: var(--text-dim); margin: 0 auto 22px; max-width: 52ch; }
.end .plan-cta { display: inline-block; width: auto; min-width: 240px; margin: 0; }

/* ---- terms of sale ------------------------------------------------------ */
/* The site footer is footer.css's and the same on every page (AQ-275). The
   terms of sale belong only to the pages that sell, so they close the page
   content above it. */
.sale-terms { max-width: 90ch; margin: 56px auto 0;
              font-size: 12.5px; line-height: 1.6; color: var(--text-dim); text-align: center; }

/* ---- responsive --------------------------------------------------------- */
@media (max-width: 900px) {
  .plans { grid-template-columns: 1fr; }
  /* NO REORDERING. This used to pull the recommended card to the front on a
     phone, which is the usual advice and is wrong here: the four tiers are an
     escalation — Free, Monthly, Annual, Team — and moving Annual to the top
     broke the sequence a reader is using to work out where they fit. It also
     read as three cards plus a stray one. Operator's call, 1 Sep. */
  .plan-for, .plan-fx, .plan-bill, .plan-note { min-height: 0; }
  .hero { padding: 34px 0 4px; }
  .sec { padding: 48px 0 0; }
}
@media (max-width: 560px) {
  .wrap { padding: 0 16px; }
  .band { grid-template-columns: 1fr; gap: 22px; }
  .nav-a.is-hideable { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}
@media print {
  .nav, .end, .seg { display: none; }
  body { background: #fff; color: #000; }
}

/* ---- enterprise plus ---------------------------------------------------- */
.eplus {
  /* margin-TOP only. As `margin: 26px 0 0` this reset margin-left to 0, and
     because it is declared after the shared breakout rule it won the cascade —
     leaving the band 1320px wide starting at left -496, half of it off-screen
     to the left. A shorthand quietly overwriting a longhand set elsewhere. */
  margin-top: 26px; padding: 30px 30px 28px;
  background: var(--panel); border: 1px solid var(--grid); border-radius: 18px;
  /* Brand edge down the leading side: it is a tier, not a footnote, and it has
     to read as one without borrowing the recommended card's full treatment. */
  box-shadow: inset 3px 0 0 var(--brand);
}
.eplus-in {
  display: grid; gap: 30px; align-items: start;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
}
.eplus-k {
  font-family: var(--mono); font-size: 10.5px; font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase; color: var(--brand);
  margin: 0 0 8px;
}
.eplus-h {
  font-family: var(--serif); font-weight: 600; margin: 0 0 10px;
  font-size: clamp(22px, 3vw, 30px); letter-spacing: -.015em;
}
.eplus-p { margin: 0; color: var(--text-dim); font-size: 15px; max-width: 54ch; }
.eplus-list { list-style: none; margin: 0 0 18px; padding: 0; display: grid; gap: 9px; }
.eplus-list li {
  position: relative; padding-left: 26px;
  font-size: 14px; line-height: 1.42; color: var(--text-dim);
}
.eplus-list b { color: var(--text); font-weight: 600; }
.eplus-list li::before {
  content: ""; position: absolute; left: 3px; top: 6px;
  width: 11px; height: 6px;
  border-left: 2px solid var(--brand); border-bottom: 2px solid var(--brand);
  transform: rotate(-45deg);
}
.eplus .plan-cta { margin: 0; }
.eplus-note { font-size: 12.5px; color: var(--faint); margin: 10px 0 0; text-align: center; }

/* ---- enquiry form ------------------------------------------------------- */
.enq { max-width: 780px; margin: 0 auto; }
/* Off-screen, not display:none. A hidden input is the first thing a bot skips
   and the first thing a screen reader announces; this is invisible to both and
   still filled by anything that fills every field it can find. */
.enq-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.enq-grid { display: grid; gap: 15px; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.enq-f { display: flex; flex-direction: column; gap: 6px; font-size: 13.5px; }
.enq-f > span { font-weight: 600; color: var(--text); }
.enq-f em { font-style: normal; font-weight: 400; color: var(--faint); }
.enq-wide { grid-column: 1 / -1; }
.enq-f input, .enq-f select, .enq-f textarea {
  font: inherit; font-size: 15px; color: var(--text);
  background: var(--field); border: 1px solid var(--grid);
  border-radius: 9px; padding: 11px 12px; width: 100%;
  /* iOS zooms the page on focus for anything under 16px; 15px plus the
     viewport's own scale is the line where it stops doing that. */
  min-height: 46px;
}
.enq-f textarea { min-height: 104px; resize: vertical; line-height: 1.45; }
.enq-f input:focus, .enq-f select:focus, .enq-f textarea:focus {
  border-color: var(--brand); outline: 2px solid var(--brand); outline-offset: 1px;
}
.enq-f input::placeholder, .enq-f textarea::placeholder { color: var(--faint); }
.enq-foot {
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
  margin: 20px 0 0;
}
.enq-send { width: auto; min-width: 210px; margin: 0; }
.enq-msg { font-size: 13.5px; color: var(--text-dim); margin: 0; }
.enq-msg.is-bad { color: var(--down); }
.enq-note { font-size: 12.5px; color: var(--faint); margin: 14px 0 0; max-width: 62ch; }
.enq-done { font-size: 16px; color: var(--text); margin: 0; padding: 18px 0; }

@media (max-width: 1180px) {
  .plans--four { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .plans--four, .eplus { max-width: 100%; width: 100%; margin-left: 0; transform: none; }
}
@media (max-width: 860px) {
  .eplus-in { grid-template-columns: 1fr; gap: 20px; }
  .enq-grid { grid-template-columns: 1fr; }
}
@media (max-width: 700px) {
  .plans--four { grid-template-columns: 1fr; }
  .plans--four .plan-for { min-height: 0; }
  .eplus { padding: 24px 20px; }
  .enq-send { width: 100%; }
}

/* ---- redeem ------------------------------------------------------------- */
.code-form { margin-bottom: 22px; }
#codeInput {
  font-family: var(--mono); font-size: 19px; letter-spacing: .12em;
  text-transform: uppercase; max-width: 15ch;
}
/* A rule with the word on it, rather than two forms stacked with nothing
   between them saying they are alternatives. */
.or-line {
  display: flex; align-items: center; gap: 14px;
  margin: 26px auto; max-width: 780px;
  font-size: 12.5px; color: var(--faint);
}
.or-line::before, .or-line::after {
  content: ""; flex: 1; height: 1px; background: var(--grid);
}
.enq--slim { margin-bottom: 0; }
.code-key {
  font-family: var(--mono); font-size: 20px; letter-spacing: .1em;
  background: var(--field); border: 1px solid var(--grid); border-radius: 10px;
  padding: 14px 16px; margin: 14px 0; word-break: break-all; user-select: all;
}

/* ---- enterprise, the quieter of the two bands --------------------------- */
/* Same construction as Enterprise Plus so they read as a pair, one step down
   in emphasis so the order still escalates: four cards, then this, then a
   custom build. Its rail is --faint rather than --brand for that reason. */
.eplus--ent { box-shadow: inset 3px 0 0 var(--faint); margin-top: 22px; }
.eplus--ent .eplus-k { color: var(--text-dim); }
.eplus--ent .eplus-list li::before {
  border-left-color: var(--up); border-bottom-color: var(--up);
}

/* ---- the preview shots -------------------------------------------------- */
/* width/height are on every <img> so the browser reserves the box before the
   file arrives. Without them the collage collapses to nothing and then shoves
   the comparison table down as each shot lands, which on a slow connection is
   the page jumping under a reader's cursor. */
.shot { margin: 0 0 28px; }
.shot img {
  display: block; width: 100%; height: auto;
  border: 1px solid var(--grid); border-radius: 12px;
  background: var(--bg);
}
/* PRODUCT WINDOWS, NOT RAW CROPS. Each capture sits in a frame with the wire's
   own navy title bar naming the page it was taken from, so a crop of a
   regulator strip reads as a piece of a product rather than a stray table.
   The frame body stays white in both themes because the captures are light-
   theme captures; a dark frame around a light screenshot is a hole in the
   page. The bar is a literal, not a token, for the same reason. */
.shot-frame {
  border: 1px solid var(--grid); border-radius: 14px; overflow: hidden;
  background: #FFFFFF;
  box-shadow: 0 1px 2px rgba(10,32,50,.06), 0 18px 40px -18px rgba(10,32,50,.35);
}
.shot-frame img { border: 0; border-radius: 0; cursor: zoom-in; }
/* the tour's windows are dark-theme captures: a dark body, or the white shows
   at the rounded corners as a hairline halo (AQ-524) */
.shot-frame--dark { background: #081B2B; }
.shot-bar {
  display: flex; align-items: center; gap: 10px; min-height: 36px; padding: 0 10px 0 12px;
  background: #0A2032; color: #B7C9D9;
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .08em; text-transform: uppercase;
}
.shot-bar .dots { display: inline-flex; gap: 5px; flex: 0 0 auto; }
.shot-bar .dots i { display: block; width: 9px; height: 9px; border-radius: 50%; background: rgba(255,255,255,.22); }
.shot-bar .shot-url { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.shot-bar .shot-num { color: #fff; font-weight: 600; margin-right: 4px; }
.shot-zoom {
  margin-left: auto; flex: 0 0 auto; min-height: 26px; padding: 3px 9px;
  background: transparent; border: 1px solid rgba(255,255,255,.38); border-radius: 6px;
  color: #fff; font: inherit; letter-spacing: .08em; cursor: zoom-in;
}
.shot-zoom:hover, .shot-zoom:focus-visible { border-color: #fff; background: rgba(255,255,255,.1); outline: none; }
.shot-frame:hover { box-shadow: 0 1px 2px rgba(10,32,50,.08), 0 22px 48px -18px rgba(10,32,50,.45); }
/* The enlarged view: the capture at the size it was taken at (2x captures at
   half their pixels, 1x at their pixels), panning in both directions on a
   small screen rather than shrinking back into illegibility. */
/* AQ-749: preview paints above the real shared header and cookie notice. */
.lb { position: fixed; inset: 0; z-index: 20000; background: rgba(4,14,24,.88); display: flex; flex-direction: column; }
.lb[hidden] { display: none; }
.lb-x {
  position: absolute; top: 14px; right: 16px; z-index: 1; min-height: 34px; padding: 6px 12px;
  background: #0A2032; border: 1px solid rgba(255,255,255,.5); border-radius: 8px; color: #fff;
  font-family: var(--mono); font-size: 11px; letter-spacing: .08em; cursor: pointer;
}
.lb-x:hover, .lb-x:focus-visible { border-color: #fff; outline: none; }
.lb-cap {
  position: absolute; left: 16px; top: 20px; right: 120px; color: #B7C9D9;
  font-family: var(--mono); font-size: 11px; letter-spacing: .08em; text-transform: uppercase;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.lb-scroll { flex: 1; overflow: auto; padding: 64px 24px 32px; cursor: zoom-out; }
.lb-scroll img {
  display: block; margin: 0 auto; max-width: none; height: auto; cursor: default;
  border-radius: 10px; background: #fff; box-shadow: 0 30px 80px -20px rgba(0,0,0,.7);
}
body.lb-open { overflow: hidden; }
/* ---- the tour: five windows, one at a time (all of them without JS) ---- */
.tour { margin: 6px 0 34px; }
.tour-tabs { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; margin: 0 0 16px; }
.tour:not(.is-js) .tour-tabs { display: none; }
.tour-tab {
  font-family: var(--mono); font-size: 11px; letter-spacing: .08em; text-transform: uppercase;
  min-height: 40px; padding: 8px 14px; border: 1px solid var(--grid); border-radius: 9px;
  background: var(--panel); color: var(--text-dim); cursor: pointer;
}
.tour-tab:hover { border-color: var(--brand); color: var(--text); }
.tour-tab[aria-selected="true"] { background: #0A2032; border-color: #0A2032; color: #fff; }
.tour-tab:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.tour-panel { margin: 0 0 22px; }
.tour.is-js .tour-panel { display: none; }
.tour.is-js .tour-panel.is-on { display: block; }
.tour-panel--text .shot-frame { max-width: 760px; margin-inline: auto; }
/* the numbers strip: figures with the noun that gives them weight */
.figs {
  list-style: none; margin: 0 0 40px; padding: 22px 8px;
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 18px;
  border-top: 1px solid var(--grid); border-bottom: 1px solid var(--grid);
}
.figs li { text-align: center; }
.figs b {
  display: block; font-family: var(--serif); font-weight: 600; font-size: clamp(30px, 4vw, 44px);
  line-height: 1; letter-spacing: -.02em; color: var(--text); margin-bottom: 8px;
}
.figs span { display: block; font-size: 13px; color: var(--text-dim); line-height: 1.4; max-width: 22ch; margin: 0 auto; }
@media (max-width: 720px) { .figs { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.sub-h {
  font-family: var(--serif); font-weight: 600; font-size: clamp(20px, 2.6vw, 26px);
  letter-spacing: -.01em; text-align: center; margin: 0 0 8px;
}
.tour-cta { display: flex; justify-content: center; gap: 12px; flex-wrap: wrap; margin: 6px 0 0; }
.tour-cta .plan-cta { display: inline-flex; width: auto; padding: 12px 22px; margin: 0; }
.shot figcaption {
  font-size: 13px; color: var(--text-dim); margin: 12px 2px 0; line-height: 1.5;
}
.shot figcaption b { color: var(--text); font-weight: 600; }
.shot--wide { margin-bottom: 34px; }
/* THE MEMO IS A CROP OF A TEXT COLUMN, not a frame of a whole page, so it
   arrives at a different scale from everything else in the section: 1500px of
   image against the deal row's 2360, both stretched to the same width. Left to
   fill the column it renders its type about 1.6x the size of the frames above
   and reads as a different product photographed on a different day.

   Capped and centred rather than re-shot, because there is no width to re-shoot
   at: the memo column is ~750 CSS px inside a 1180 viewport, and widening the
   band to match the others drags in the index rail and the newsletter card,
   which is a picture of the desk and not of the memo. 760px puts the image at
   about 2x — retina-sharp — and brings its type back in line. A block of prose
   also simply wants to be narrower than a table. */
.shot--text .shot-frame { max-width: 760px; margin-inline: auto; }
.shot-pair { display: grid; gap: 24px; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.shot, .shot-frame { min-width: 0; }
/* The two lower shots are crops of tall pages, capped and anchored to the top —
   the interesting half of a table is always its first rows.
   
   NO FADE MASK HERE, because there is nothing left to fade. At 752px wide a
   1180x620 shot renders 396px tall against the 430px cap below, so it is not
   cropped; in two columns it is ~341 against 340, which is one pixel. The
   mid-row cut that prompted a fade came from the OLD 340px cap, and raising
   that cap removed it.

   A gradient mask WAS added for it first, and blamed for the previews
   rendering blank in a screenshot. That was wrong: the images were complete,
   opacity 1 and correctly laid out the whole time, and a forced repaint made
   them appear with no mask involved — the capture was not compositing lazily
   loaded images. Nothing here is evidence against mask-image; it simply is not
   needed. Recorded because "don't mask, it renders blank" would be false
   guidance to inherit. */
.shot-pair .shot img {
  max-height: 340px; object-fit: cover; object-position: top left;
}
@media (max-width: 800px) {
  .shot-pair { grid-template-columns: minmax(0, 1fr); }
  /* Stacked, they are not competing for width, so a shallower letterbox is
     just wasted detail — let them run taller. */
  .shot-pair .shot img { max-height: 430px; }
}

/* The theme toggle draws ◑ / ◐ from the self-hosted subset above. */
#themeBtn, .themebtn { font-family: "AXIOM Symbols", var(--sans); }

/* ---- the analytics consent banner ---------------------------------------
   assets/ga.js appends <div class="axw-consent"> to the body, and its rules
   lived only in app.css and universe.css. This page loads neither, so on the
   live pricing page (measured 14 Sep 2026) the banner rendered as static,
   unstyled text after the footer — 25px tall, 7,666px down the page, seen by
   nobody — while the cookie policy describes a banner that asks. The same
   rules as app.css; the focus ring is this file's own :focus-visible rule. */
.axw-consent {
  position: fixed; left: 16px; bottom: 16px; z-index: 4000; max-width: 356px;
  display: flex; flex-direction: column; gap: 11px;
  background: var(--panel); border: 1px solid var(--grid); border-radius: 11px;
  padding: 14px 15px; box-shadow: 0 12px 36px rgba(0,0,0,.30);
  font-family: var(--mono); font-size: 11.5px; line-height: 1.55; color: var(--text-dim);
}
.axw-consent-btns { display: flex; gap: 8px; justify-content: flex-end; }
.axw-consent button {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .08em;
  text-transform: uppercase; padding: 7px 15px; border-radius: 8px; cursor: pointer;
  border: 1px solid var(--grid); background: transparent; color: var(--text-dim);
  transition: background-color .12s, border-color .12s, color .12s, filter .12s;
  min-height: 44px;
}
.axw-consent .axw-consent-yes { background: var(--brand); border-color: var(--brand); color: #fff; font-weight: 600; }
.axw-consent .axw-consent-yes:hover { filter: brightness(1.08); }
.axw-consent .axw-consent-no:hover { border-color: var(--text-dim); color: var(--text); }
@media (max-width: 520px) { .axw-consent { left: 10px; right: 10px; bottom: 10px; max-width: none; } }

/* ---- AQ-284: the line beside the pay buttons, and the renewal terms -------
   This replaced the rules for a bordered consent panel — a heading, a
   definition list, a fieldset of four checkboxes and three sizes of fine
   print. The band made the contract look like a sixth pricing tier standing
   between the reader and the button. A line of text under the cards reads as
   what it is: the small print of the thing above it.

   NOT ONE COLOUR BELOW IS INVENTED. Every value is a token this file already
   declares in both palettes, so it follows the theme toggle for free.
   --faint would be too quiet for terms that have to be legible, so the
   paragraph is --text-dim, which the audit measures at 4.5:1 or better in
   both palettes at this size. The refusal message keeps --cont, as the one it
   replaces did. */
.buy { margin-top: 18px; }
.buy-terms {
  margin: 0 auto; max-width: 92ch;
  font-size: 13px; line-height: 1.6; color: var(--text-dim); text-align: center;
}
.buy-terms b { color: var(--text); font-weight: 600; }
.buy-msg {
  margin: 10px 0 0; text-align: center;
  font-size: 13.5px; line-height: 1.5; color: var(--text-dim);
}
.buy-msg.is-bad { color: var(--cont); font-weight: 600; }
.buy-hold {
  margin: 10px 0 0; text-align: center;
  font-size: 13px; line-height: 1.5; color: var(--cont);
}

/* THE RENEWAL TERMS, beside the button they qualify rather than further up the
   page. Reads as the second half of the trial note directly above it — "No
   charge today" / "then £45 a month, VAT added, cancel any time" — so the
   obligation to pay is stated where the order is placed, which is what CCR
   2013 reg 14(4) is about. */
.renew { font-size: 12px; line-height: 1.4; color: var(--text-dim); text-align: center; }
.plan .renew { margin: -10px 0 14px; }

/* AQ-361: the working enquiry layout shared with the Entertainment reference. */
#enquire { display: grid; grid-template-columns: minmax(0, .7fr) minmax(0, 1.3fr); gap: 48px; align-items: start; }
.enq-intro { padding-top: 28px; }
.enq-intro .sec-h { margin-bottom: 14px; }
.enq-intro .sec-p { max-width: 31ch; margin-bottom: 24px; }
.enq-email { color: var(--brand-l); font-size: 14px; text-underline-offset: 4px; }
#enquire .enq { width: 100%; max-width: none; min-width: 0; margin: 0; padding: 32px; background: var(--bg); border: 1px solid var(--grid); border-radius: 8px; }
#enquire .enq-grid { gap: 22px 20px; }
#enquire .enq-f { gap: 8px; min-width: 0; }
#enquire .enq-f :is(input, select, textarea) { font-size: 16px; min-height: 48px; border-radius: 6px; background: var(--bg2); }
#enquire .enq-f textarea { min-height: 136px; line-height: 1.55; }
#enquire .enq-foot { margin-top: 24px; }
#enquire .enq-send { min-height: 48px; }
#enquire .enq-note { margin-top: 18px; line-height: 1.6; }
@media (max-width: 960px) {
  #enquire { grid-template-columns: 1fr; gap: 24px; }
  .enq-intro { padding-top: 0; }
  .enq-intro .sec-p { max-width: 48ch; margin-bottom: 14px; }
}
@media (max-width: 600px) {
  #enquire .enq { padding: 24px 20px; }
  #enquire .enq-grid { gap: 20px; }
  #enquire .enq-send { width: 100%; min-width: 0; }
}
.public-redeem { border-block: 1px solid var(--grid); margin-top: 40px; }
.public-redeem > summary { cursor: pointer; padding: 18px 0; font-size: 13px; font-weight: 500; }
.public-redeem .code-form { margin-top: 0; }
