/* ============================================================
   Components added 15-09-2026 for the full site build: the pages
   beyond the one-page draft (capabilities, report showcase, contact,
   and the three legal pages).

   Same rule as base.css - nothing chromatic, no font family named.
   Everything reads the tokens set by theme.css, so a direction swap
   carries these along for free.
   ============================================================ */

/* ---------- page header (interior pages, no boot sequence) ---------- */

/* Clearance is measured from the fixed bar rather than guessed. --chrome-h is
   the nav's real height, so the heading cannot slide underneath it the way it
   did when the bar was two rows deep and this was a bare clamp(). The extra
   room on top of it is breathing space, not clearance. */
.phead { padding: calc(var(--chrome-h) + clamp(2rem, 5vh, 3.5rem)) 0 clamp(2.2rem, 4.5vh, 3rem); }
.phead > .wrap > .meta { display: inline-block; margin-bottom: .55rem; }
.phead h1 {
  font-size: clamp(2rem, 5vw, 4rem);
  margin-bottom: 1.2rem;
  max-width: 18ch;
  /* Anybody's space is wide at this size; tighter gaps keep the words reading
     as one line of thought (Andy, 05-10-2026). */
  word-spacing: -.07em;
}
.phead .lede { max-width: 58ch; }
/* Pricing: the sticky price bar sits straight under the lede, so the
   term and currency buttons read as part of the introduction. */
.phead--flush { padding-bottom: 0; }
.phead--flush .lede { margin-bottom: .5rem; }

/* ---------- fact tiles: a number and what it counts ---------- */

.facts { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--gutter); }
@media (max-width: 940px) { .facts { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 480px) { .facts { grid-template-columns: 1fr; } }

.fact {
  background: var(--card);
  border: 1px solid var(--card-line);
  padding: 1.5rem 1.35rem 1.4rem;
  display: flex; flex-direction: column; gap: .5rem;
  transition: border-color .3s, transform .45s cubic-bezier(.2,.8,.2,1);
}
.fact:hover { border-color: var(--card-line-hi); transform: translateY(-4px); }
.fact__n {
  font-family: var(--display);
  font-weight: 400;
  font-variation-settings: "wdth" 108;
  font-size: clamp(1.9rem, 3.6vw, 2.9rem);
  line-height: 1; letter-spacing: -.03em;
}
.fact__n small { font-size: .42em; letter-spacing: -.01em; color: var(--soft); margin-left: .3em; }
/* "5,000+": the plus is part of the figure, so it is set large and centred
   on the digits, not dropped to the baseline like a unit. */
.fact__plus { font-size: 1.5em; line-height: 0; font-weight: 300; vertical-align: -.08em; margin-left: .02em; color: var(--signal); }

/* The animated digits. font-variant-numeric keeps every glyph the same width
   while the number counts up, so the tile does not jitter as it runs, and
   min-width stops the row reflowing when it starts from a single 0. */
.fact__n i {
  font-style: normal;
  font-variant-numeric: tabular-nums;
  display: inline-block;
}
.fact__k {
  font-family: var(--mono); font-size: .58rem; letter-spacing: .11em;
  text-transform: uppercase; color: var(--signal);
}
.fact__s { color: var(--soft); font-size: .88rem; line-height: 1.45; margin: 0; }

/* ---------- capability rows: the function list ---------- */

.caps { border-top: 1px solid var(--fg); }

.cap {
  display: grid;
  /* Title column sized to the longest title, so the prose sits close to it
     rather than across half the page (Andy, 05-10-2026). */
  grid-template-columns: 4rem minmax(0, 27rem) minmax(0, 46rem);
  gap: var(--gutter);
  padding: 1.7rem 0;
  border-bottom: 1px solid var(--line);
  /* Title centred on the prose beside it; rows that open with a short intro
     above a list (.cap--list) centre on that intro instead. */
  align-items: center;
  transition: background .25s;
}
.cap:hover { background: var(--rail-bg); }
.cap__n { font-family: var(--mono); font-size: .6rem; letter-spacing: .1em; color: var(--dim); }
.cap--list { align-items: start; }
.cap--list > .cap__n, .cap--list > div:first-of-type { padding-top: .75rem; }
.cap__t {
  font-family: var(--display);
  font-weight: 500;
  font-variation-settings: "wdth" 104;
  font-size: clamp(1.05rem, 1.7vw, 1.35rem);
  line-height: 1.15; letter-spacing: -.015em;
  margin: 0;
}
.cap__d { color: var(--soft); margin: 0; font-size: .94rem; }
.cap__d b { color: var(--fg); font-weight: 500; }
.cap__tag {
  display: inline-block; margin-top: .6rem;
  font-family: var(--mono); font-size: .52rem; letter-spacing: .1em;
  text-transform: uppercase; color: var(--dim);
  border: 1px solid var(--line); padding: .22rem .5rem;
}
.cap__tag--soon { color: var(--signal); border-color: var(--signal); }

/* One extracted field per line, each a label and what it gives you. A comma
   list reads as one blurred capability; a ruled column reads as a spec, and a
   reader can point at the row they care about. */
.fields { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--line); }
.fields li {
  display: flex; gap: 1rem; align-items: center;
  padding: .52rem 0;
  border-bottom: 1px solid var(--line);
}
.fields b {
  font-weight: 500; color: var(--fg); font-size: .9rem;
  flex: 0 0 11rem;
}
.fields span { color: var(--dim); font-size: .84rem; }
.fields li::before {
  content: ""; flex: none;
  width: 3px; height: 3px;
  background: var(--signal);
}
@media (max-width: 560px) {
  .fields li { flex-wrap: wrap; gap: .25rem .7rem; }
  .fields b { flex-basis: auto; }
  .fields span { flex: 1 1 100%; padding-left: calc(3px + .7rem); }
}
@media (max-width: 860px) {
  .cap { grid-template-columns: 2.6rem 1fr; row-gap: .7rem; }
  .cap__d { grid-column: 2; }
}

/* The rest of the data points: small, no descriptions, in columns, only to
   show how much more there is under the twelve explained ones. */
.fields-more {
  list-style: none; margin: 1.1rem 0 0; padding: 0;
  columns: 3 9rem; column-gap: 1.2rem;
  font-family: var(--mono); font-size: .56rem; letter-spacing: .06em;
  text-transform: uppercase; color: var(--dim); line-height: 1.5;
}
.fields-more li { break-inside: avoid; padding: .18rem 0; }

/* Deliverable rows (How it works, 03): the whole row links to its section on
   What you get, and a picture of it opens under the text on hover, focus, or
   once the row has been scrolled to (site.js adds .is-seen). */
.cap--link { color: inherit; text-decoration: none; cursor: pointer; row-gap: 0; }
.cap--link .cap__t::after { content: " \2192"; color: var(--signal); font-family: var(--mono); font-size: .8em; }
.cap__media {
  grid-column: 3;
  display: grid; grid-template-rows: 1fr;
  transition: grid-template-rows .6s cubic-bezier(.2,.8,.2,1), opacity .5s;
}
/* Closed until reached only while site.js runs (html.js), so with scripts
   off the pictures show instead of waiting for an .is-seen that never comes. */
.js .cap__media { grid-template-rows: 0fr; opacity: 0; }
.cap__media > * { min-height: 0; overflow: hidden; }
.cap__media img { margin-top: 1.4rem; width: 100%; height: auto; display: block; border: 1px solid var(--card-line); background: #fff; }
.js .cap--link:hover .cap__media, .js .cap--link:focus-visible .cap__media, .js .cap--link.is-seen .cap__media {
  grid-template-rows: 1fr; opacity: 1;
}
@media (prefers-reduced-motion: reduce) {
  .js .cap__media { grid-template-rows: 1fr; opacity: 1; transition: none; }
}
@media print { .js .cap__media { grid-template-rows: 1fr; opacity: 1; } }
@media (max-width: 860px) { .cap--link { row-gap: .7rem; } .cap__media { grid-column: 2; } }

/* The archive bundle, drawn: a zip file and its real file name pattern. */
.zipfile { display: flex; align-items: center; gap: 1rem; margin-top: 1.4rem; }
.zipfile img, .cap__media .zipfile img { width: 46px; height: auto; flex: none; margin: 0; border: 0; background: none; }
.zipfile__n { font-family: var(--mono); font-size: .72rem; letter-spacing: .02em; color: var(--signal); word-break: break-all; }

/* ---------- report showcase slots ---------- */

.slots { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--gutter); }
@media (max-width: 900px) { .slots { grid-template-columns: 1fr; } }

.slot {
  background: var(--card);
  border: 1px solid var(--card-line);
  display: flex; flex-direction: column;
  transition: border-color .3s;
}
.slot:hover { border-color: var(--card-line-hi); }
.slot__head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; padding: .95rem 1.1rem; border-bottom: 1px solid var(--card-line);
}
.slot__who { font-family: var(--mono); font-size: .62rem; letter-spacing: .1em; text-transform: uppercase; }
.slot__state { font-family: var(--mono); font-size: .52rem; letter-spacing: .1em; text-transform: uppercase; color: var(--dim); }
.slot__state--ready { color: var(--signal); }

/* The 16:9 stage where a real deck screenshot goes. Until one is
   dropped in, it renders a labelled placeholder rather than a broken
   image, so the page is presentable before the assets exist. */
.slot__stage {
  aspect-ratio: 16 / 9;
  background: var(--shade);
  position: relative; overflow: hidden;
  display: grid; place-items: center;
}
.slot__stage img { width: 100%; height: 100%; object-fit: cover; }

/* Texture for the EMPTY state only. :has() scopes it off the moment a real
   screenshot is dropped in - without that guard the ::after paints a diagonal
   hatch and a coloured bloom straight over the deck image, and the first
   person to fill a slot concludes the deck looks terrible.
   The :not(:has(img)) also covers browsers without :has() in the safe
   direction: they drop the whole selector, so the texture simply never
   renders, rather than rendering on top of a screenshot. */
.slot__stage:not(:has(img))::after {
  content: "";
  position: absolute; inset: 0; pointer-events: none;
  background:
    linear-gradient(135deg, var(--hatch) 0 1px, transparent 1px) 0 0 / 18px 18px,
    radial-gradient(circle at 62% 38%, var(--bloom) 0%, transparent 60%);
}
.slot__stage img ~ .slot__ph { display: none; }
.slot__ph {
  position: relative; z-index: 1; text-align: center;
  font-family: var(--mono); font-size: .58rem; letter-spacing: .12em;
  text-transform: uppercase; color: var(--dim);
  padding: 1rem;
}
.slot__body { padding: 1.2rem 1.1rem 1.4rem; display: flex; flex-direction: column; gap: .75rem; flex: 1; }
.slot__body p { margin: 0; color: var(--soft); font-size: .92rem; }
.slot__list { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: .4rem; }
.slot__list li {
  font-family: var(--mono); font-size: .58rem; letter-spacing: .08em;
  text-transform: uppercase; color: var(--dim);
  display: flex; gap: .55rem;
}
.slot__list li::before { content: "/"; color: var(--signal); }

/* ---------- deck page sequence (what a client actually gets) ------- */

.seq { display: grid; grid-template-columns: repeat(5, 1fr); gap: var(--gutter); }
@media (max-width: 1000px) { .seq { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px) { .seq { grid-template-columns: 1fr; } }

.step { border-top: 1px solid var(--fg); padding-top: .9rem; }
.step__n { font-family: var(--mono); font-size: .56rem; letter-spacing: .1em; color: var(--signal); }
.step__t {
  font-family: var(--display); font-weight: 500;
  font-variation-settings: "wdth" 104;
  font-size: 1.02rem; letter-spacing: -.01em;
  margin: .45rem 0 .45rem;
}
.step__d { margin: 0; color: var(--soft); font-size: .86rem; line-height: 1.45; }

/* ---------- contact form ---------- */

.form { display: grid; gap: 1.1rem; max-width: 40rem; }
.form[hidden] { display: none; }
.field { display: grid; gap: .45rem; }
.field > label {
  font-family: var(--mono); font-size: .58rem; letter-spacing: .11em; word-spacing: -.35em;
  text-transform: uppercase; color: var(--dim);
}
.field input, .field textarea {
  font-family: var(--body); font-size: .95rem; color: var(--fg);
  background: var(--card);
  border: 1px solid var(--card-line);
  padding: .8rem .9rem;
  width: 100%;
  transition: border-color .25s;
}
/* A transparent outline, not none: invisible here, but Windows High Contrast
   paints it, where the border colour change alone does not show. */
.field input:focus, .field textarea:focus { border-color: var(--signal); outline: 2px solid transparent; outline-offset: -2px; }
.field textarea { min-height: 9rem; resize: vertical; }
.field__hint { font-size: .78rem; color: var(--dim); margin: 0; }
.consent { display: flex; gap: .7rem; align-items: start; font-size: .85rem; color: var(--soft); }
.consent input { margin-top: .25rem; accent-color: var(--signal); flex: none; }

/* Request form additions (19-09-2026): inline validation, the phone prefix
   picker, the plan summary, the sent state. All read tokens only. */
.field .opt {
  font-family: var(--mono); font-size: .52rem; letter-spacing: .1em;
  color: var(--dim); margin-left: .5rem;
}
/* "optional" sits inside the box on the right, like the placeholder, and
   stays while you type (07-10-2026). */
.inbox { position: relative; }
.inbox .opt--in {
  position: absolute; right: .9rem; top: 50%; transform: translateY(-50%);
  margin: 0; pointer-events: none;
}
.inbox textarea + .opt--in { top: 1.05rem; transform: none; }
.field .inbox input, .field .inbox textarea { padding-right: 6.2rem; }
.field__err { font-size: .78rem; color: var(--signal); margin: 0; }
.field__err[hidden] { display: none; }
.field.is-bad input, .field.is-bad textarea { border-color: var(--signal); }

/* Free report length: two tick boxes with the estimate beside them (07-10-2026). */
.weeks { border: 0; margin: 0; padding: 0; min-width: 0; }
.weeks legend {
  padding: 0; margin-bottom: .45rem;
  font-family: var(--mono); font-size: .58rem; letter-spacing: .11em; word-spacing: -.35em;
  text-transform: uppercase; color: var(--dim);
}
.weeks__row { display: flex; flex-wrap: wrap; align-items: center; gap: .6rem 1.4rem; }
.weeks__opt {
  display: inline-flex; align-items: center; gap: .5rem; cursor: pointer;
  font-size: .95rem; color: var(--fg);
  border: 1px solid var(--card-line); background: var(--card); padding: .7rem .9rem;
  transition: border-color .25s;
}
.weeks__opt:has(input:checked) { border-color: var(--signal); }
.field .weeks__opt input { width: auto; padding: 0; border: 0; margin: 0; accent-color: var(--signal); }
.weeks__when { margin: 0; font-size: .82rem; color: var(--soft); flex: 1 1 14rem; white-space: pre-line; line-height: 1.5; }

.phone { display: grid; grid-template-columns: 9.5rem minmax(0, 1fr); gap: .6rem; }
.dial { position: relative; }
.dial__list {
  position: absolute; z-index: 30; left: 0; top: calc(100% + 2px);
  min-width: 100%; width: max-content; max-width: min(22rem, calc(100vw - 2 * var(--gutter)));
  max-height: 16rem; overflow-y: auto;
  margin: 0; padding: .3rem 0; list-style: none;
  background: var(--card); border: 1px solid var(--card-line-hi);
  box-shadow: 0 14px 30px -16px rgba(0,0,0,.45);
}
.dial__list[hidden] { display: none; }
.dial__list li {
  display: grid; grid-template-columns: 4.2rem minmax(0, 1fr) auto; gap: .8rem;
  align-items: baseline; padding: .5rem .8rem; cursor: pointer; font-size: .88rem;
}
.dial__list li b { font-family: var(--mono); font-weight: 400; font-size: .72rem; }
.dial__list li i { font-family: var(--mono); font-style: normal; font-size: .58rem; letter-spacing: .1em; color: var(--dim); }
.dial__list li:hover, .dial__list li.is-active { background: var(--shade); }
.dial__list li.is-active b { color: var(--signal); }

/* The two column heads of the order section, "Your plan" and "What happens
   next": one rule so they cannot drift apart. */
.cfg__h {
  font-family: var(--display); font-weight: 400; font-size: 1.05rem;
  font-variation-settings: "wdth" 108; letter-spacing: -.01em;
  margin: 0 0 .8rem;
}
.cfgsum ul { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--fg); }
.cfgsum li {
  display: flex; justify-content: space-between; gap: 1rem;
  padding: .55rem 0; border-bottom: 1px solid var(--line); font-size: .9rem;
}
.cfgsum li b { font-family: var(--mono); font-weight: 400; font-size: .72rem; font-variant-numeric: tabular-nums; white-space: nowrap; }
.cfgsum li.tot { border-bottom: 1px solid var(--fg); }
.cfgsum li.tot b { color: var(--signal); }
.cfgsum.is-empty { font-size: .9rem; color: var(--soft); border-top: 1px solid var(--fg); padding-top: .8rem; }

/* Anchor jumps to the form land under the sticky chrome plus the price bar,
   not behind them. */
#order { scroll-margin-top: calc(var(--chrome-h) + 5rem); }
.form__status { font-size: .85rem; color: var(--soft); margin: 0; }
.form__status[hidden] { display: none; }
.form__status.is-bad { color: var(--signal); }
.done { border-top: 1px solid var(--fg); padding-top: 1.4rem; max-width: 40rem; }
.done[hidden] { display: none; }
.done h3 { margin: .6rem 0 .8rem; }
.done p { margin: 0 0 .8rem; }

/* The honeypot: out of the layout, out of the tab order, out of the
   accessibility tree, but present for anything that fills every input. */
.hp { position: absolute; left: -9999px; top: -9999px; width: 1px; height: 1px; overflow: hidden; }

.buildbar__go {
  font-family: var(--mono); font-size: .58rem; letter-spacing: .12em;
  text-transform: uppercase; text-decoration: none;
  color: var(--on-signal); background: var(--signal);
  padding: .6rem .9rem; margin-left: .4rem; white-space: nowrap;
  transition: opacity .25s;
}
.buildbar__go:hover { opacity: .85; }
@media (max-width: 760px) { .buildbar__go { margin-left: auto; } }

@media (max-width: 620px) {
  .phone { grid-template-columns: 7.5rem minmax(0, 1fr); }
}
/* A 320px phone left about 40px to type the number in beside the code and
   the "optional" tag, so on narrow screens the two stack (07-10-2026). */
@media (max-width: 24em) {
  .phone { grid-template-columns: minmax(0, 1fr); }
}

/* ---------- long-form prose: the three legal pages ---------- */

.prose { max-width: 68ch; }
.prose h2 {
  font-family: var(--display); font-weight: 500;
  font-variation-settings: "wdth" 104;
  font-size: clamp(1.15rem, 2vw, 1.5rem);
  letter-spacing: -.015em; line-height: 1.15;
  margin: 3rem 0 .9rem;
  padding-top: 1.3rem; border-top: 1px solid var(--line);
}
.prose h3 {
  font-family: var(--body); font-weight: 600; font-size: 1rem;
  margin: 1.8rem 0 .5rem;
}
.prose p, .prose li { color: var(--soft); font-size: .95rem; }
.prose ul, .prose ol { padding-left: 1.2rem; display: flex; flex-direction: column; gap: .4rem; }
.prose a { color: var(--signal); text-underline-offset: 3px; }
/* body carries overflow-x:hidden, so a wide table inside .prose would be
   CLIPPED rather than scrollable - silently unreadable on a phone, on the two
   pages that legally have to be readable. Stack these into label/value rows
   instead, the same treatment .cmp gets in base.css. */
.prose table { width: 100%; border-collapse: collapse; margin: 1rem 0; }
@media (max-width: 640px) {
  /* display:block turns the table itself into the scroll container, so no
     wrapper div is needed in the markup and the header row stays visible -
     which matters, because these rows carry no per-cell labels to fall back
     on the way .cmp does. */
  .prose table { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .prose th, .prose td { white-space: normal; min-width: 8.5rem; }
}
.prose th, .prose td { text-align: left; padding: .7rem .8rem; border-bottom: 1px solid var(--line); font-size: .88rem; vertical-align: top; }
.prose th { font-family: var(--mono); font-size: .58rem; letter-spacing: .1em; text-transform: uppercase; color: var(--dim); font-weight: 400; }
.prose td { color: var(--soft); }

/* A placeholder that must be filled before the site goes public.
   Deliberately loud - it is meant to be impossible to ship by accident. */
.todo {
  display: inline-block;
  background: var(--signal); color: var(--on-signal);
  font-family: var(--mono); font-size: .62rem; letter-spacing: .08em;
  padding: .1rem .4rem;
}

/* ---------- about page: the two people behind Victic ---------- */

/* Each person is an Instagram post card (.post, base.css), the profile in the
   caption where Instagram puts it. One column on phones: two cards across a
   phone leave a caption too narrow to read. */
.people {
  display: grid; grid-template-columns: minmax(0, 24rem); justify-content: center;
  gap: var(--gutter); margin-bottom: 3.5rem;
}
@media (min-width: 40em) { .people { grid-template-columns: repeat(2, minmax(0, 24rem)); } }
.person { min-width: 0; }
/* No avatar picture yet: an empty ring on the shade colour. */
span.post__av { display: block; background: var(--shade); }
/* Portrait, as Instagram allows: the photos are 3:4 phone shots, and a
   square would crop off the top of a head or the chin (Andy, 09-10-2026). */
/* A white mat around each photo, like a print (Andy, 15-10-2026).
   content-box keeps the photo itself at 3:4 inside the border. */
.person .post__media { aspect-ratio: 3 / 4; box-sizing: content-box; border: .6rem solid var(--frame, var(--card)); }
.person .post__media .todo { position: absolute; left: .75rem; bottom: .75rem; z-index: 1; }
.post__cap { padding: .2rem .75rem .9rem; }
.person__name {
  font-family: var(--display); font-weight: 500;
  font-variation-settings: "wdth" 104;
  font-size: 1.1rem; letter-spacing: -.01em; line-height: 1.2; margin: 0 0 .4rem;
}
.post__cap p { color: var(--soft); font-size: .88rem; margin: 0; }

.legal-nav { display: flex; flex-wrap: wrap; gap: 1.2rem; margin-bottom: 2.5rem; }
.legal-nav a {
  font-family: var(--mono); font-size: .62rem; letter-spacing: .1em;
  text-transform: uppercase; color: var(--dim); text-decoration: none;
  border-bottom: 1px solid transparent; padding-bottom: 2px;
}
.legal-nav a:hover, .legal-nav a[aria-current] { color: var(--fg); border-color: var(--signal); }

/* The plain-language summary at the top of each legal page. It restates the
   clauses below and never adds to them: if the two ever differ, the clauses
   win, and the box says so. */
.short {
  border-left: 2px solid var(--signal);
  padding: .2rem 0 .2rem 1.2rem;
  margin: 0 0 2.5rem;
}
.short .meta { display: block; margin-bottom: .6rem; }
.short ul { margin: 0; }
.short p { margin: .8rem 0 0; font-size: .85rem; }

/* ---------- richer footer for a multi-page site ---------- */

/* Note on the left, the logo with mail and domain in the middle, Site and
   Legal side by side on the right (Andy, 05-10-2026). */
.sitefoot { border-top: 1px solid var(--line); padding: 1.8rem 0 1.6rem; margin-top: clamp(3rem, 8vh, 6rem); }
.sitefoot__cols { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); column-gap: var(--gutter); align-items: start; }
.sitefoot__links { justify-self: end; display: flex; gap: clamp(2rem, 5vw, 4.5rem); }
.sitefoot__brand { align-self: start; display: flex; flex-direction: column; align-items: center; gap: .6rem; }
.sitefoot__brand img { height: 35px; width: auto; display: block; }
.sitefoot__brand span { font-family: var(--mono); font-size: .58rem; letter-spacing: .1em; color: var(--dim); }
@media (max-width: 760px) { .sitefoot__cols { grid-template-columns: 1fr; row-gap: 2rem; } .sitefoot__links { justify-self: start; } .sitefoot__brand { align-items: flex-start; } }
.sitefoot h3 {
  font-family: var(--mono); font-size: .58rem; letter-spacing: .11em;
  text-transform: uppercase; color: var(--dim); font-weight: 400; margin: 0 0 .9rem;
}
.sitefoot ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .35rem; }
.sitefoot a { color: var(--soft); text-decoration: none; font-size: .88rem; }
.sitefoot a:hover { color: var(--fg); }
.sitefoot__note { color: var(--soft); font-size: .88rem; max-width: 42ch; margin: 0; }

/* ============================================================
   PRICING BUILDER (added 19-09-2026)

   Same rule as everything above: no colour literal, no font family,
   only tokens from theme.css, so a direction swap carries it along.

   Every price lives in the markup as a data attribute. site.js reads
   them and does the arithmetic, so nothing here or there restates a
   number that could drift.
   ============================================================ */

/* ---------- the running total, pinned under the nav ----------

   OPAQUE, not translucent. The first build used --nav-bg over a blur
   and the cards underneath read straight through the total, which is
   the one number on the page that has to be unambiguous.

   Sticky rather than fixed: it scrolls into place under the bar and
   holds, so it never covers the page heading on arrival.

   It is always present, because it carries the billing-term buttons
   and those are worth having before a tier is picked. Until then it
   renders compact: term buttons and a quiet prompt, no empty total. */
.buildbar {
  position: sticky; top: var(--chrome-h); z-index: 40;
  background: var(--bg);
  border-bottom: 1px solid var(--fg);
  box-shadow: 0 10px 24px -18px rgba(0,0,0,.55);
}
.buildbar__row {
  display: flex; align-items: center; gap: clamp(1rem, 3vw, 2.2rem);
  padding: .85rem 0;
}

/* The pieces sit together in the middle of the bar rather than being
   thrown to opposite edges of a 1440px viewport. Only the total is
   pushed right, and its label sits directly under it. */
/* Term and currency buttons as one cluster: a small gap between them,
   and stretch so the one-line currency pill matches the two-line terms. */
.buildbar__ctl { display: flex; align-items: stretch; gap: .5rem; flex: 0 0 auto; }
.buildbar__who { min-width: 0; flex: 1 1 auto; }
.buildbar__sum {
  font-family: var(--mono); font-size: .58rem; letter-spacing: .1em;
  text-transform: uppercase; color: var(--fg);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.buildbar__once {
  font-family: var(--mono); font-size: .55rem; letter-spacing: .08em;
  color: var(--signal); margin-top: .25rem;
}
.buildbar__fig { display: flex; align-items: center; gap: .6rem; margin-left: auto; }
.buildbar__tot {
  font-family: var(--display); font-weight: 400;
  font-variation-settings: "wdth" 108;
  font-size: clamp(1.5rem, 3vw, 2.2rem);
  line-height: 1; letter-spacing: -.03em; font-variant-numeric: tabular-nums;
}
.buildbar__tot small {
  font-family: var(--body); font-size: .32em; letter-spacing: 0;
  color: var(--soft); margin-left: .3em; font-variant-numeric: normal;
}
.buildbar__note {
  font-family: var(--mono); font-size: .55rem; letter-spacing: .1em;
  text-transform: uppercase; color: var(--dim);
}
.buildbar__more {
  appearance: none; background: none; border: 0; cursor: pointer; padding: 0;
  font-family: var(--mono); font-size: .55rem; letter-spacing: .1em;
  text-transform: uppercase; color: var(--signal);
  text-decoration: underline; text-underline-offset: .3em;
  white-space: nowrap; margin-right: 1rem;
}

/* Before anything is picked there is no total to show, so the figure
   and the working are out and the bar is just the term buttons. */
.is-empty .buildbar__fig,
.is-empty .buildbar__more,
.is-empty .buildbar__lines { display: none; }
.is-empty .buildbar__sum { color: var(--dim); }

.buildbar__lines { display: none; list-style: none; margin: 0; padding: 0 0 .9rem; }
.is-open:not(.is-empty) .buildbar__lines { display: block; }
.buildbar__lines li {
  display: flex; justify-content: space-between; gap: 1rem;
  padding: .38rem 0; border-top: 1px solid var(--line);
  font-size: .85rem; color: var(--soft);
}
.buildbar__lines b { color: var(--fg); font-weight: 500; font-variant-numeric: tabular-nums; }

/* Anything you chose can be dropped from here too. Without it the working
   showed you a charge and gave you no way to act on it. */
.buildbar__lines .lx {
  appearance: none; background: none; border: 1px solid var(--line);
  color: var(--dim); cursor: pointer; line-height: 1;
  font-family: var(--mono); font-size: .8rem;
  width: 1.4rem; height: 1.4rem; flex: 0 0 auto;
  transition: border-color .2s, color .2s;
}
.buildbar__lines .lx:hover { border-color: var(--signal); color: var(--signal); }
.buildbar__lines li { align-items: center; }
/* The label takes the free space, so every amount sits on the right edge;
   with space-between alone, a row with a remove button put its amount in
   the middle (07-10-2026). */
.buildbar__lines li > span:first-child { flex: 1 1 auto; min-width: 0; }
/* Lines with no control keep the same right edge as the ones that have one. */
.buildbar__lines li:not(:has(.lx)) { padding-right: calc(1.4rem + 1rem); }

@media (max-width: 760px) {
  .buildbar__row { flex-wrap: wrap; row-gap: .7rem; }
  .buildbar__fig { margin-left: 0; width: 100%; }
}
/* The five buttons measure 347px, which pushed 360 and 375px phones sideways
   (07-10-2026). Below 24em they tighten, and on anything narrower still
   (a zoomed phone, enlarged text) the currency pair drops to a second line. */
.buildbar__ctl { flex-wrap: wrap; row-gap: .5rem; max-width: 100%; }
@media (max-width: 24em) {
  .terms button { padding: .5rem .4rem; letter-spacing: .06em; }
}
/* The working must not make the sticky bar taller than a landscape phone,
   or its lower lines can never be scrolled into view. */
.is-open:not(.is-empty) .buildbar__lines { max-height: 40vh; overflow-y: auto; }

/* ---------- term buttons, now living inside the bar ---------- */

.terms { display: inline-flex; flex: 0 0 auto; border: 1px solid var(--line); }
.terms button {
  appearance: none; background: none; border: 0; cursor: pointer;
  font-family: var(--mono); font-size: .55rem; letter-spacing: .1em;
  text-transform: uppercase; color: var(--dim);
  padding: .5rem .8rem; border-right: 1px solid var(--line);
  transition: color .25s, background .25s;
}
.terms button:last-child { border-right: 0; }
.terms button:hover { color: var(--fg); }
.terms button[aria-pressed="true"] { background: var(--signal); color: var(--on-signal); }
.terms button small { display: block; font-size: .85em; letter-spacing: .05em; opacity: .75; }

/* ---------- plan cards ---------- */

.plans { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--gutter); }
@media (max-width: 900px) { .plans { grid-template-columns: 1fr; } }

/* The whole card is the control, so it carries the pointer. The button
   inside it stays a real button for keyboard and screen readers; the
   script skips the card handler when the click already landed on it. */
.plan {
  background: var(--card);
  border: 1px solid var(--card-line);
  padding: 1.7rem 1.5rem 1.6rem;
  display: flex; flex-direction: column; gap: .9rem;
  cursor: pointer;
  transition: border-color .3s, transform .45s cubic-bezier(.2,.8,.2,1);
}
.plan:hover { border-color: var(--card-line-hi); transform: translateY(-4px); }
.plan.is-on { border-color: var(--signal); box-shadow: inset 0 0 0 1px var(--signal); }

/* The tier name is a PRODUCT NAME, not a label. At mono-caption size it
   read as a word in the sentence on the button ("add wide"), which is
   what confused a first-time reader. Display face, heading size. */
.plan__name {
  font-family: var(--display); font-weight: 500;
  font-variation-settings: "wdth" 104;
  font-size: clamp(1.15rem, 2vw, 1.5rem);
  line-height: 1; letter-spacing: -.02em;
  color: var(--signal);
}
.plan__price {
  font-family: var(--display); font-weight: 400;
  font-variation-settings: "wdth" 108;
  font-size: clamp(2rem, 3.8vw, 3rem);
  line-height: 1; letter-spacing: -.03em; font-variant-numeric: tabular-nums;
}
.plan__price small {
  font-family: var(--body); font-size: .3em; letter-spacing: 0;
  color: var(--soft); margin-left: .45em; font-variant-numeric: normal;
}
.plan__what { color: var(--fg); font-size: .95rem; margin: 0; font-weight: 500; }
.plan__list { list-style: none; margin: .2rem 0 0; padding: 0; border-top: 1px solid var(--line); }
.plan__list li {
  padding: .55rem 0; border-bottom: 1px solid var(--line);
  color: var(--soft); font-size: .88rem; line-height: 1.45;
}
.plan__list li b { color: var(--fg); font-weight: 500; }

/* Just "Add". Naming the tier here turned the button into a phrase
   ("add extended") that reads as an instruction about an extension. */
.plan__pick {
  appearance: none; cursor: pointer; width: 100%; margin-top: auto;
  background: none; border: 1px solid var(--fg); color: var(--fg);
  font-family: var(--mono); font-size: .58rem; letter-spacing: .11em;
  text-transform: uppercase; padding: .75rem 1rem;
  transition: background .25s, color .25s, border-color .25s;
}
.plan__pick:hover { background: var(--fg); color: var(--bg); }
.plan__pick[aria-pressed="true"] { background: var(--signal); border-color: var(--signal); color: var(--on-signal); }

/* ---------- frequency rows ---------- */

.opts { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--fg); }
.opts li { border-bottom: 1px solid var(--line); }
.opts button {
  appearance: none; background: none; border: 0; cursor: pointer; width: 100%;
  display: grid; grid-template-columns: 1.6rem minmax(0,1fr) auto;
  gap: 1rem; align-items: baseline; text-align: left;
  padding: .95rem .6rem; color: inherit; font: inherit;
  transition: background .25s;
}
.opts button:hover { background: var(--rail-bg); }
.opts .opt__dot {
  width: .62rem; height: .62rem; border: 1px solid var(--dim);
  border-radius: 50%; display: block; align-self: center;
}
.opts button[aria-pressed="true"] .opt__dot { background: var(--signal); border-color: var(--signal); }
.opts .opt__t { font-weight: 500; }
.opts .opt__d { color: var(--soft); font-size: .9rem; display: block; margin-top: .2rem; }
.opts .opt__p {
  font-family: var(--mono); font-size: .72rem; letter-spacing: .06em;
  color: var(--signal); white-space: nowrap; font-variant-numeric: tabular-nums;
}
@media (max-width: 620px) {
  .opts button { grid-template-columns: 1.6rem minmax(0,1fr); row-gap: .4rem; }
  .opts .opt__p { grid-column: 2; }
}

.is-off .opts { opacity: .32; pointer-events: none; }

/* ---------- flat extras ---------- */

.addons { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--fg); }
.addons li {
  display: grid; grid-template-columns: minmax(0,1fr) auto; gap: var(--gutter);
  align-items: baseline; padding: 1.05rem 0; border-bottom: 1px solid var(--line);
}
.addons b { font-weight: 500; }
.addons li > div:first-child span {
  color: var(--soft); font-size: .9rem; display: block; margin-top: .25rem;
}
.addons .addons__p {
  font-family: var(--mono); font-size: .72rem; letter-spacing: .06em;
  color: var(--signal); white-space: nowrap; font-variant-numeric: tabular-nums;
}
.addons__add {
  appearance: none; cursor: pointer; background: none;
  border: 1px solid var(--line); color: var(--dim);
  font-family: var(--mono); font-size: .55rem; letter-spacing: .1em;
  text-transform: uppercase; padding: .45rem .8rem; margin-top: .5rem;
  transition: background .25s, color .25s, border-color .25s;
}
.addons__add:hover { border-color: var(--fg); color: var(--fg); }
.addons__add[aria-pressed="true"] { background: var(--signal); border-color: var(--signal); color: var(--on-signal); }

@media (max-width: 620px) {
  .addons li { grid-template-columns: minmax(0,1fr); row-gap: .4rem; }
}

/* ============================================================
   COMPARISON TABLES AND QUESTIONS

   Lifted out of a second pricing draft that was deleted on
   19-09-2026 once the first one won. The tables and the FAQ were the
   half of that draft worth keeping.
   ============================================================ */


.cmpt { width: 100%; border-collapse: collapse; font-size: .9rem; }
.cmpt caption {
  text-align: left; font-family: var(--mono); font-size: .58rem;
  letter-spacing: .11em; text-transform: uppercase; color: var(--signal);
  padding-bottom: .8rem;
}
.cmpt th, .cmpt td { padding: .7rem .6rem; border-bottom: 1px solid var(--line); text-align: left; }
.cmpt thead th {
  font-family: var(--mono); font-size: .58rem; letter-spacing: .1em;
  text-transform: uppercase; color: var(--fg); border-bottom: 1px solid var(--fg);
}
.cmpt tbody th { font-weight: 400; color: var(--soft); width: 46%; }
.cmpt td { text-align: center; color: var(--fg); font-variant-numeric: tabular-nums; }
.cmpt .no { color: var(--dim); }
.cmpt tr.grp th {
  font-family: var(--mono); font-size: .55rem; letter-spacing: .1em;
  text-transform: uppercase; color: var(--dim); padding-top: 1.4rem;
}
@media (max-width: 700px) {
  .cmpt { font-size: .82rem; }
  .cmpt th, .cmpt td { padding: .55rem .35rem; }
  .cmpt tbody th { width: 40%; }
}

/* ---------- questions ---------- */

.faq { border-top: 1px solid var(--fg); }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  cursor: pointer; list-style: none; padding: 1.1rem .4rem;
  font-weight: 500; display: flex; justify-content: space-between; gap: 1rem;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: "+"; color: var(--signal); font-family: var(--mono); }
.faq details[open] summary::after { content: "\2212"; }
.faq summary:hover { background: var(--rail-bg); }
.faq p { color: var(--soft); margin: 0; padding: 0 .4rem 1.2rem; max-width: 70ch; }

/* ============================================================
   PRICING, round three (19-09-2026)
   ============================================================ */

/* The background artefact layer read straight through the comparison
   table and the grid lines fought the row rules. The table sits on its
   own opaque surface now. */
.cmpwrap {
  background: var(--card);
  border: 1px solid var(--card-line);
  padding: clamp(1rem, 2.5vw, 1.8rem);
}
.cmpwrap + .cmpwrap { margin-top: var(--gutter); }

/* A table is a lot of page to scroll past when you only want one of the
   two. Collapsed by default, opened by its own heading. */
.cmpwrap > summary {
  cursor: pointer; list-style: none;
  display: flex; align-items: baseline; justify-content: space-between; gap: 1rem;
  font-family: var(--display); font-weight: 500;
  font-variation-settings: "wdth" 104;
  font-size: clamp(1rem, 1.5vw, 1.2rem); letter-spacing: -.02em;
  color: var(--signal);
}
.cmpwrap > summary::-webkit-details-marker { display: none; }
.cmpwrap > summary::after {
  content: "+"; font-family: var(--mono); font-size: 1rem; color: var(--signal);
}
.cmpwrap[open] > summary::after { content: "\2212"; }
/* Nearly touching the header rule, the way a tier name sits on its card,
   instead of a heading hanging a paragraph above the table it names. */
.cmpwrap[open] > summary { margin-bottom: .15rem; }
.cmpwrap[open] .cmpt thead th { padding-top: 0; }

/* Header labels sit over the column they name. They were left aligned
   while every value under them was centred. */
.cmpt thead th:not(:first-child),
.cmpt td { text-align: center; }
.cmpt thead th { vertical-align: bottom; }

/* ---------- questions ---------- */

/* The heading sat a full band above its own list. */
.faq { margin-top: 1.1rem; }

/* ---------- savings calculator (pricing) ----------
   Rows in the .cfgsum idiom, each with a minus / value / plus stepper. */
.calc { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--fg); }
.calc li {
  display: flex; justify-content: space-between; align-items: center; gap: 1rem;
  padding: .55rem 0; border-bottom: 1px solid var(--line); font-size: .9rem;
}
.stepper { display: inline-flex; align-items: center; gap: .2rem; flex: 0 0 auto; }
.stepper button {
  appearance: none; background: none; border: 0; cursor: pointer; padding: 0;
  width: 1.6rem; height: 1.6rem; line-height: 1;
  font-family: var(--mono); font-size: .9rem; color: var(--dim);
  transition: color .2s;
}
.stepper button:hover:not(:disabled) { color: var(--signal); }
.stepper button:disabled { opacity: .3; cursor: default; }
.stepper output {
  min-width: 4.6rem; text-align: center;
  font-family: var(--mono); font-size: .72rem; font-variant-numeric: tabular-nums; white-space: nowrap;
}
/* The report drafting the manual figure leaves out, named under the saving
   so the prices above stay one clean column. */
.calc__plus {
  margin: .5rem 0 0; text-align: right;
  font-family: var(--mono); font-size: .62rem; letter-spacing: .04em; color: var(--soft);
}

/* ---------- a screenshot of the real product (what-we-do) ---------- */
.shot { margin: clamp(1.6rem, 3vh, 2.4rem) 0 0; }
.shot--flush { margin-top: 0; }
.shot img { width: 100%; height: auto; display: block; border: 1px solid var(--card-line); background: #fff; }
.shot figcaption {
  margin-top: .6rem; font-family: var(--mono); font-size: .55rem;
  letter-spacing: .1em; text-transform: uppercase; color: var(--dim);
}

/* ---------- coming soon ----------
   A product that is shown but not sold. Greyed rather than hidden, so the
   reader knows it is on the way, and inert: no hover lift, no pointer, no
   control inside it. Pricing keeps the markup free of data-* hooks, so the
   builder never counts it; this only makes it look the part. */
/* Everything but the heading and its tag is greyed, so "Coming soon" keeps
   its colour and reads first. */
.soon > :not(.sechead):not(.soon__head),
.soon .sechead > :not(.soon__head),
.cmpwrap--soon .cmpt { opacity: .45; filter: grayscale(1); }
.soon .plan, .soon .plan:hover { cursor: default; transform: none; border-color: var(--card-line); }
.soon__head { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem 1rem; }
.soon__head .cap__tag { margin-top: 0; }
/* Pricing's collapsed radar (07-10-2026): the title greys too; only the tag keeps its colour. */
.soon__head h2 { color: var(--dim); }
.soon__t {
  font-family: var(--display); font-weight: 500;
  font-variation-settings: "wdth" 104;
  font-size: clamp(1.4rem, 2.6vw, 2rem);
  line-height: 1.05; letter-spacing: -.02em; margin: 0;
}
.soon__d { color: var(--soft); max-width: 46rem; margin: 1rem 0 1.4rem; }
.soon__cmp { margin-bottom: 1.6rem; }
div.soon + .caps { margin-top: clamp(2.6rem, 5vh, 3.6rem); }
.caps--soon .cap__n, .caps--soon .cap__t, .caps--soon .cap__d { opacity: .45; filter: grayscale(1); }
.caps--soon .cap:hover { background: none; }
.opts__row {
  display: grid; grid-template-columns: 1.6rem minmax(0,1fr);
  gap: 1rem; align-items: baseline; padding: .95rem .6rem;
}
.cmpwrap--soon > summary { color: var(--dim); }
.cmpwrap--soon > summary .cap__tag { margin: 0 0 0 .8rem; vertical-align: middle; }

/* ---------- demo report tiles + viewer (reports page) ----------
   Tile: the deck's cover, blurred, with a "See report" pill. Viewer: a modal
   <dialog> with the slides in one centred column and explainers on the page
   margins, each tied to its spot on the slide by a line. The geometry is all
   percentages of the slide, so it holds at any slide width. */
.slot__stage--demo { cursor: pointer; }
.slot__stage--demo img { filter: blur(3px); transform: scale(1.03); transition: filter .5s, transform .6s cubic-bezier(.2,.8,.2,1); }
.slot__stage--demo:hover img, .slot__stage--demo:focus-within img { filter: none; transform: none; }
.demo__pill {
  position: absolute; inset: 50% auto auto 50%; transform: translate(-50%, -50%);
  appearance: none; cursor: pointer; z-index: 2;
  background: var(--card); color: var(--signal); border: 1px solid var(--signal);
  border-radius: 999px; padding: .8rem 1.5rem;
  font-family: var(--mono); font-size: .66rem; letter-spacing: .12em; text-transform: uppercase;
  transition: background .25s, color .25s;
}
.demo__pill:hover, .demo__pill:focus-visible { background: var(--signal); color: var(--on-signal); }
.demo__note {
  margin: 0 0 1.2rem; padding: .8rem 1rem; border-left: 2px solid var(--signal);
  background: var(--card); color: var(--soft); font-size: .9rem; max-width: 52rem;
}
.demo__note b { color: var(--fg); font-weight: 500; }

.dv {
  --note-w: 15rem; --gap: 2.2rem;
  --sw: min(60rem, calc(100vw - 2 * (var(--note-w) + var(--gap)) - 4rem));
  position: fixed; inset: 0; width: 100%; height: 100%; max-width: none; max-height: none;
  margin: 0; padding: 0; border: 0; overflow: auto; overscroll-behavior: contain;
  background: var(--bg);
  color: var(--fg); opacity: 0; transition: opacity .25s;
}
.dv::backdrop { background: color-mix(in srgb, var(--bg) 60%, transparent); backdrop-filter: blur(6px); }
.dv.is-in { opacity: 1; }
.dv__bar {
  position: sticky; top: 0; z-index: 5;
  display: flex; align-items: center; gap: 1rem; justify-content: space-between;
  padding: .8rem clamp(1rem, 3vw, 2rem); background: var(--bg); border-bottom: 1px solid var(--line);
}
.dv__bar p { margin: 0; font-size: .82rem; color: var(--soft); }
.dv__bar b { font-family: var(--mono); font-size: .62rem; letter-spacing: .1em; text-transform: uppercase; color: var(--fg); font-weight: 400; margin-right: .8rem; }
.dv__x {
  appearance: none; cursor: pointer; flex: none; background: none; color: var(--fg);
  border: 1px solid var(--fg); padding: .5rem .9rem;
  font-family: var(--mono); font-size: .58rem; letter-spacing: .1em; text-transform: uppercase;
}
.dv__x:hover { background: var(--fg); color: var(--bg); }
.dv__body { padding: 2.5rem 1rem 4rem; }
.dv__col { width: calc(var(--sw) + 2 * (var(--note-w) + var(--gap))); max-width: 100%; margin: 0 auto; }
.dv__stack { display: flex; flex-direction: column; gap: 2.35rem; }
/* Scroll reveal, as on the rest of the site: a slide rises in when it is
   scrolled to (demo.js adds .is-shown), its dots, lines and notes a beat later. */
.dv__row { margin: 0; width: var(--sw); max-width: 100%; margin-inline: auto; opacity: 0; transform: translateY(48px); transition: opacity .7s cubic-bezier(.2,.8,.2,1), transform .8s cubic-bezier(.2,.8,.2,1); }
.dv__row.is-shown { opacity: 1; transform: none; }
.dv__pin, .dv__lines { opacity: 0; transform: translateY(30px); transition: opacity .6s cubic-bezier(.2,.8,.2,1) .14s, transform .75s cubic-bezier(.2,.8,.2,1) .14s; }
.dv__note { transform: translateY(-.72rem); }
.dv__row.is-shown .dv__pin, .dv__row.is-shown .dv__lines { opacity: 1; transform: none; }
.dv__slide { position: relative; box-shadow: 0 18px 50px rgba(11,12,14,.16), 0 2px 6px rgba(11,12,14,.08); background: #F5F3EE; }
.dv__slide.is-flying { transition: transform .55s cubic-bezier(.2,.8,.2,1); }
.dv__slide img { display: block; width: 100%; height: auto; }

.dv__pin { position: absolute; inset: 0; pointer-events: none; z-index: 1; }
.dv__dot {
  position: absolute; left: var(--x); top: var(--y); width: .7rem; height: .7rem; margin: -.35rem 0 0 -.35rem;
  border-radius: 50%; background: var(--signal); box-shadow: 0 0 0 4px rgba(var(--signal-rgb), .22);
}
.dv__lines { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
.dv__lines line { stroke: var(--signal); stroke-width: 1; }
/* The note's title sits level with the end of its line (--ny). */
.dv__note {
  position: absolute; top: var(--ny); width: var(--note-w);
  display: flex; flex-direction: column; gap: .3rem; font-size: .84rem; line-height: 1.45; color: var(--soft);
}
.dv__note b { font-family: var(--display); font-weight: 500; font-size: 1.02rem; color: var(--fg); line-height: 1.15; }
.dv__pin--l .dv__note { right: calc(100% + var(--gap) + .6rem); text-align: right; }
.dv__pin--r .dv__note { left: calc(100% + var(--gap) + .6rem); }
.dv__notes { display: none; }

/* Not enough room for margins: the notes become a numbered list under each
   slide and the dots carry the numbers. */
@media (max-width: 1100px) {
  .dv { --sw: calc(100vw - 2rem); }
  .dv__col { width: auto; }
  .dv__lines, .dv__note { display: none; }
  .dv__dot { width: 1.15rem; height: 1.15rem; margin: -.575rem 0 0 -.575rem; }
  .dv__pin::after {
    content: attr(data-n); position: absolute; left: var(--x); top: var(--y); transform: translate(-50%, -50%);
    font-family: var(--mono); font-size: .55rem; color: var(--on-signal);
  }
  .dv__notes {
    display: flex; flex-direction: column; gap: .5rem; margin: 1rem 0 0; padding-left: 1.4rem;
    font-size: .88rem; color: var(--soft);
  }
  .dv__notes b { color: var(--fg); font-weight: 500; }
  .dv__notes li::marker { font-family: var(--mono); color: var(--signal); }
}
@media (prefers-reduced-motion: reduce) {
  .dv, .dv__row, .dv__pin, .dv__lines, .slot__stage--demo img { transition: none; }
}

/* ---------- what you get: the four deliverables (05-10-2026) ---------- */
#deck, #notion, #drive, #archive { scroll-margin-top: calc(var(--chrome-h) + 1rem); }
.jump { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .6rem; }
.jump a {
  position: relative; overflow: hidden;
  font-family: var(--mono); font-size: .58rem; letter-spacing: .1em; text-transform: uppercase;
  color: var(--fg); text-decoration: none; border: 1px solid var(--card-line-hi); padding: .45rem .7rem;
  transition: color .3s, border-color .3s;
}
/* The same fill as .btn on Home: the cobalt rises into the button. */
.jump a span { position: relative; z-index: 2; }
.jump a::before {
  content: ""; position: absolute; inset: 0; z-index: 1;
  background: var(--signal);
  transform: translateY(101%);
  transition: transform .44s cubic-bezier(.2,.75,.25,1);
}
.jump a:hover::before, .jump a:focus-visible::before { transform: translateY(0); }
.jump a:hover, .jump a:focus-visible { color: var(--on-signal); border-color: var(--signal); }
.tier { margin-left: .6rem; color: var(--signal); }
.subh2 {
  font-family: var(--display); font-variation-settings: "wdth" 108; font-weight: 400;
  font-size: clamp(1.6rem, 3vw, 2.4rem); line-height: 1.05; letter-spacing: -.02em; margin: .7rem 0 0;
}
/* Notion and Drive marks beside their names (07-10-2026). Sized in em, so the
   same tag reads tiny in a jump pill, small on a How it works row and larger
   on a section heading. */
.mark { display: inline-block; height: 1.15em; width: auto; vertical-align: -.2em; margin-right: .5em; }
.jump .mark { height: 1.5em; vertical-align: -.45em; margin-right: .6em; }
.subh2 .mark { height: .8em; vertical-align: -.04em; margin-right: .35em; }
/* The deck's mark is a tiny cover of the demo report. */
.mark--deck { aspect-ratio: 16 / 9; object-fit: cover; border: 1px solid var(--card-line-hi); background: var(--card); }
.jump .mark--deck { height: 1.3em; vertical-align: -.35em; }
/* How it works rows: the mark gets its own slot between the number and the
   title, so a title that wraps stays in one column beside it. */
.cap__t:has(.mark) { display: flex; align-items: center; gap: .55em; }
.cap__t .mark { flex: none; margin: 0; height: 1.25em; width: 2em; object-fit: contain; }
.cap__t .mark--deck { height: 1.1em; object-fit: cover; }
/* The arrow rides on the title text, not as a third flex item that squeezes it. */
.cap--link .cap__t:has(.mark)::after { content: none; }
.cap--link .cap__t > span::after { content: "\00a0\2192"; color: var(--signal); font-family: var(--mono); font-size: .8em; }
/* Without :has() (older Firefox) the rule above that removes the title's own
   arrow is dropped, so drop this one instead rather than show two. */
@supports not selector(:has(a)) { .cap--link .cap__t > span::after { content: none; } }
/* The heading runs the full row so "Google Drive" never folds; the note keeps
   the old five-column measure. */
.dlv__head .note { max-width: 36rem; }
.subhead {
  font-family: var(--display); font-weight: 500; font-variation-settings: "wdth" 104;
  font-size: clamp(1.15rem, 2vw, 1.5rem); line-height: 1.15; letter-spacing: -.015em; margin: .6rem 0 0;
}
.shot__ph {
  aspect-ratio: 1400 / 984; display: grid; place-items: center;
  border: 1px solid var(--card-line); background: var(--shade);
  font-family: var(--mono); font-size: .58rem; letter-spacing: .12em; text-transform: uppercase; color: var(--dim);
}
.ziptree { border: 1px solid var(--card-line); background: var(--card); padding: 1.4rem 1.6rem 1.6rem; }
.ziptree .zipfile { margin-top: 0; padding-bottom: 1.1rem; border-bottom: 1px solid var(--line); }
.ziptree__t {
  margin: 1.1rem 0 0; font-family: var(--mono); font-size: .7rem; line-height: 1.9;
  color: var(--soft); white-space: pre; overflow-x: auto;
}
.ziptree__t i { font-style: normal; color: var(--dim); }

/* What you get header on one line; the jump row centred under it. */
.phead--wide h1 { max-width: none; }

/* Period deck head: the description left, the demo notice in the right half
   beside it, so the two demo tiles sit straight under the description. */
.deckhead { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--gutter); align-items: end; margin-bottom: clamp(1.2rem, 2.5vh, 1.8rem); }
.deckhead .sechead { margin-bottom: 0; }
.deckhead .sechead .note { margin-bottom: 0; }
#deck { padding-top: 1.4rem !important; }
.deckhead .demo__note { margin: 0; font-size: .82rem; }
@media (max-width: 860px) { .deckhead { grid-template-columns: 1fr; } }

/* Notion, Drive, archive: the picture starts level with the list's top rule. */
.dlv { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gutter); row-gap: 1.3rem; }
.dlv__head { grid-column: 1 / -1; grid-row: 1; }
.dlv__list { grid-column: 1 / span 5; grid-row: 2; }
.dlv__pic { grid-column: 6 / -1; grid-row: 2; }
@media (max-width: 1080px) {
  .dlv__head, .dlv__list, .dlv__pic { grid-column: 1 / -1; grid-row: auto; }
  .dlv__pic { margin-top: 2rem; }
}

/* The deck picture on How it works carries the demo pill. */
.cap__media .deckpic { position: relative; }
.deckpic img { filter: blur(3px); transition: filter .5s; }
.cap--link:hover .deckpic img { filter: none; }
.deckpic .demo__pill { top: calc(50% + .7rem); }

/* A demo deck tile used as a link (Home, one place): the reports page's
   blurred cover and pill, opening What you get with that deck open. */
.demo-link { display: block; text-decoration: none; color: inherit; }
.demo-link:hover .demo__pill, .demo-link:focus-visible .demo__pill { background: var(--signal); color: var(--on-signal); }
.demo-link__cap { margin: .7rem 0 0; }

/* ---------- Windows High Contrast (forced colours, 07-10-2026) ----------
   The system palette replaces our colours, and a state shown only by a
   background or a box-shadow disappears: no visible selected term, plan or
   frequency. Paint those with the system highlight instead. */
@media (forced-colors: active) {
  .terms button[aria-pressed="true"],
  .plan__pick[aria-pressed="true"],
  .addons__add[aria-pressed="true"] { forced-color-adjust: none; background: Highlight; color: HighlightText; border-color: Highlight; }
  .opts button[aria-pressed="true"] .opt__dot { forced-color-adjust: none; background: Highlight; border-color: Highlight; }
  .plan.is-on { outline: 3px solid Highlight; outline-offset: -3px; }
  .nav__links a[aria-current] { text-decoration: underline; text-underline-offset: .35em; }
  /* The logo is a dark-on-transparent image the system cannot recolour. */
  .brand__logo { forced-color-adjust: none; background: #E9EAEC; padding: 2px 4px; }
}

/* ---------- print ---------- */
@media print {
  .boot, .chrome, .buildbar { display: none; }
  .boot ~ main { margin-top: 0; }
  .btn { print-color-adjust: exact; -webkit-print-color-adjust: exact; }
}
