/* ============================================================
   ASKDOCS — SUBPAGES
   Layout for every page that is not the cinematic home page.
   One file, not one per page: the subpages share a skeleton
   (page head → sections → closing) and forking it nine ways is
   how a design system rots.

   Nothing here invents a value. Every colour, size, space and
   curve resolves to a token in tokens.css. Radius 0, flat fills,
   red as punctuation — the same rules the home page follows.
   ============================================================ */


/* ---- Masthead, subpage rendition ---------------------------
   The home page's masthead is transparent because the hero's
   photographic plate runs to the viewport's top edge and a bar
   there reads as a white strip across it. A subpage has no
   plate — it has body copy, which scrolls under a transparent
   sticky bar and collides with the lockup. So the subpage
   rendition paints paper and draws its lower edge.

   Keyed off the ABSENCE of .cine-page rather than a modifier
   class on the header itself. That is what lets the masthead
   markup stay byte-identical on all nine pages: the difference
   is a property of the page, so the page carries it, not the
   chrome. One shared header, no per-page fork. */

html:not(.cine-page) .site-head {
  background: var(--paper);
  border-bottom: var(--bd-hair) solid var(--rule);
  pointer-events: auto;
}


/* ---- Page head ---------------------------------------------
   The subpage's opening statement. The home hero's structure —
   eyebrow, display, red bar, lead — at one step down, with the
   drawn column grid behind it. No photography: the system
   admits exactly two stills and both are spoken for. */

.page-head {
  position: relative;
  padding: var(--s-7) var(--gutter) var(--s-6);
  border-bottom: var(--bd-hair) solid var(--rule-mid);
}

.page-head__inner {
  position: relative;
  max-width: 1120px;
}

.page-head__title { margin-top: var(--s-3); }

.page-head__bar {
  width: min(240px, 60%);
  margin-top: var(--s-4);
}

.page-head__lead {
  margin-top: var(--s-4);
  max-width: 62ch;
}

/* The meta line under a legal page's title. It is real information — the
   date a policy took effect — so it takes --ink-soft (8.21:1). --ink-faint
   measures 3.14:1 on paper and fails WCAG AA for body text. */
.page-head__meta {
  margin-top: var(--s-4);
  font-size: var(--fs-caption);
  letter-spacing: var(--ls-caption);
  text-transform: uppercase;
  font-weight: 600;
  color: var(--ink-soft);
}


/* ---- Section scaffolding -----------------------------------
   .section itself comes from sections.css; these are the
   subpage's inner rhythm. */

.page-section__inner { max-width: 1120px; }

.page-section__title { max-width: 20ch; }

.page-section__lead {
  margin-top: var(--s-4);
  max-width: 62ch;
}

/* A section whose content is a single reading column. */
.page-section--prose .page-section__inner { max-width: 760px; }


/* ---- Prose -------------------------------------------------
   Long-form reading: about, legal, security. One column, one
   measure, no decoration. Headings step down from the page's
   single h1 without skipping a level. */

.prose {
  font-size: var(--fs-item);
  line-height: 1.62;
  color: var(--ink-soft);
  max-width: 68ch;
}

.prose > * + * { margin-top: var(--s-3); }

.prose h2 {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 30px;
  line-height: 1.1;
  letter-spacing: var(--ls-label);
  color: var(--ink);
  margin-top: var(--s-6);
}

.prose h3 {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 21px;
  line-height: 1.2;
  letter-spacing: var(--ls-label);
  color: var(--ink);
  margin-top: var(--s-5);
}

.prose ul, .prose ol {
  margin-top: var(--s-2);
  padding-left: var(--s-3);
}
.prose li + li { margin-top: var(--s-1); }

.prose a {
  color: var(--ink);
  border-bottom: var(--bd-hair) solid var(--red);
}
.prose a:hover { color: var(--red); }

/* A pulled-out statement inside prose — the one place a subpage
   raises its voice. Ink rail on the left, never a tinted panel. */
.prose blockquote {
  margin-top: var(--s-4);
  padding-left: var(--s-3);
  border-left: var(--bd-rail) solid var(--red);
  color: var(--ink);
  font-weight: 600;
}


/* ---- Card set ----------------------------------------------
   Beats in 3, columns in 4 — the system's set rule. Each card
   is a hairline-ruled field, not a shadowed box. */

.cards {
  display: grid;
  gap: var(--s-5) var(--split-gap);
  margin-top: var(--set-lead-in);
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}

.cards--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.cards--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.cards--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }

.card {
  padding-top: var(--s-3);
  border-top: var(--bd-panel) solid var(--rule-mid);
}

/* The one hot item in a set takes the 2px red top rule. */
.card--hot { border-top-color: var(--red); }

.card__label { margin-top: var(--s-2); }
.card__body  { margin-top: var(--s-2); }

.card__tick { margin-bottom: var(--s-3); }

/* Cards stacked in an aside rail rather than laid out in a set. */
.split__aside > .card + .card { margin-top: var(--s-4); }


/* ---- Spec table --------------------------------------------
   Requirements, formats, limits. A ruled table, not a striped
   one: rows are separated by the same hairline the page uses
   everywhere else. */

.spec {
  width: 100%;
  margin-top: var(--s-5);
  border-collapse: collapse;
  font-size: var(--fs-item);
  line-height: 1.45;
  text-align: left;
}

.spec caption {
  margin-bottom: var(--s-2);
  text-align: left;
  font-size: var(--fs-caption);
  letter-spacing: var(--ls-caption);
  text-transform: uppercase;
  font-weight: 600;
  color: var(--ink-soft);
}

.spec th,
.spec td {
  padding: var(--s-2) var(--s-2) var(--s-2) 0;
  border-bottom: var(--bd-hair) solid var(--rule);
  vertical-align: top;
}

.spec thead th {
  border-bottom: var(--bd-panel) solid var(--ink);
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--fs-caption);
  letter-spacing: var(--ls-caption);
  text-transform: uppercase;
  color: var(--ink-soft);
  white-space: nowrap;
}

.spec tbody th {
  font-weight: 700;
  color: var(--ink);
  white-space: nowrap;
  padding-right: var(--s-4);
}

.spec td { color: var(--ink-soft); }

/* A table is the one thing on these pages allowed its own
   scroller — narrower than 420px it cannot reflow honestly. */
.table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}


/* ---- Numbered steps on the red rail ------------------------
   The process component from the home page's #how, rebuilt as
   a vertical list because an install is read top to bottom. */

.install {
  position: relative;
  margin-top: var(--s-5);
  padding-left: var(--s-5);
  list-style: none;
}

/* The rail: 4px red, drawn down the full set. */
.install::before {
  content: '';
  position: absolute;
  left: 0;
  top: 6px;
  bottom: 6px;
  width: var(--bd-rail);
  background: var(--red);
}

.js .install::before {
  transform: scaleY(0);
  transform-origin: center top;
  transition: transform var(--dur-y) var(--ease);
}
.js .install.in::before { transform: scaleY(1); }

.install__step { position: relative; }
.install__step + .install__step { margin-top: var(--s-5); }

/* The node: a red square sitting astride the rail, offset by
   half its own width so it straddles the 4px exactly. */
.install__step::before {
  content: '';
  position: absolute;
  left: calc((var(--s-5) * -1) - 5px + (var(--bd-rail) / 2));
  top: 6px;
  width: 14px;
  height: 14px;
  background: var(--red);
}

.install__label { margin-top: 0; }
.install__body  { margin-top: var(--s-2); }


/* ---- Code block --------------------------------------------
   Install commands. Monospace is the one voice outside the two
   families, and it earns the exception the way a table does:
   a command that reflows is a command that fails. */

/* The same red rail the process steps carry. A command is a step in
   the install sequence, and it now looks like one instead of like a
   grey box the page happens to contain.

   It is a BORDER, not a pseudo-element: this box scrolls horizontally
   for long commands, and an absolutely-positioned rail scrolls out of
   the frame with the content. The border is painted on the scroll
   container itself and stays put. */
.code {
  margin-top: var(--s-3);
  padding: var(--s-3);
  border: var(--bd-panel) solid var(--rule-mid);
  border-left: var(--bd-rail) solid var(--red);
  background: var(--ink-wash);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.code pre {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 14px;
  line-height: 1.7;
  color: var(--ink);
  white-space: pre;
}

/* The shell prompt is punctuation, so it takes the accent. */
.code .p { color: var(--red); user-select: none; }
.code .c { color: var(--ink-faint); }


/* ---- FAQ ---------------------------------------------------
   Questions as a ruled list with deep-linkable ids. Native
   <details> so it works with no JS and stays keyboard-operable;
   the marker is drawn, because the system has no icon set. */

.faq { margin-top: var(--s-5); border-top: var(--bd-hair) solid var(--rule-mid); }

.faq__item { border-bottom: var(--bd-hair) solid var(--rule-mid); }

.faq__q {
  display: flex;
  align-items: flex-start;
  gap: var(--s-3);
  padding: var(--s-3) 0;
  cursor: pointer;
  list-style: none;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 21px;
  line-height: 1.25;
  letter-spacing: var(--ls-label);
  transition: color var(--dur-hover) var(--ease);
}
.faq__q::-webkit-details-marker { display: none; }
.faq__q:hover { color: var(--red); }

/* The marker: a red plus drawn from two rules, rotating to a
   minus when the item opens. No chevron, no icon font. */
.faq__mark {
  position: relative;
  flex: none;
  width: 16px;
  height: 16px;
  margin-top: 5px;
}
.faq__mark::before,
.faq__mark::after {
  content: '';
  position: absolute;
  inset: 50% 0 auto 0;
  height: 3px;
  margin-top: -1.5px;
  background: var(--red);
  transition: transform var(--dur-hover) var(--ease);
}
.faq__mark::after { transform: rotate(90deg); }
.faq__item[open] .faq__mark::after { transform: rotate(0deg); }

.faq__a {
  padding: 0 0 var(--s-4) calc(16px + var(--s-3));
  max-width: 68ch;
}


/* ---- Form --------------------------------------------------
   Square inputs, 2px rule, 2px red on focus, no glow — the
   input spec from the design system, at full page scale. */

.form { margin-top: var(--s-5); max-width: 640px; }

.form-field + .form-field { margin-top: var(--s-4); }

.form-field__label {
  display: block;
  margin-bottom: var(--s-1);
  font-size: var(--fs-caption);
  letter-spacing: var(--ls-caption);
  text-transform: uppercase;
  font-weight: 600;
  color: var(--ink-soft);
}

.form-field__input,
.form-field__select,
.form-field__area {
  display: block;
  width: 100%;
  padding: 14px var(--s-2);
  border: var(--bd-panel) solid var(--ink-faint);
  border-radius: var(--radius);
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--fs-item);
  line-height: 1.4;
  transition: border-color var(--dur-hover) var(--ease);
}

.form-field__area { min-height: 160px; resize: vertical; }

.form-field__input:focus,
.form-field__select:focus,
.form-field__area:focus {
  outline: none;
  border-color: var(--red);
}

.form-field__input::placeholder,
.form-field__area::placeholder { color: var(--ink-faint); }

/* The select keeps a drawn caret rather than the platform's. */
.form-field__select {
  appearance: none;
  -webkit-appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--ink) 50%),
                    linear-gradient(135deg, var(--ink) 50%, transparent 50%);
  background-position: right var(--s-2) center, calc(100% - 10px) center;
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
  padding-right: var(--s-5);
}

/* The honeypot. Off-screen rather than display:none — a bot
   that reads computed style skips hidden fields, and a real
   user never reaches it because it is not in the tab order. */
.form-field--trap {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.form__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
  align-items: center;
  margin-top: var(--s-5);
}

.form__note {
  margin-top: var(--s-3);
  font-size: 15px;
  line-height: 1.5;
  color: var(--ink-soft);                    /* AA: --ink-faint is 3.14:1 */
}

/* Submit reuses the CTA voice; a <button> needs the reset a
   link does not. */
.cta--submit {
  border: 0;
  cursor: pointer;
  font-family: var(--font-display);
}


/* ---- Status panels -----------------------------------------
   Contact form success and error. Both are ruled fields, not
   tinted alerts — the system has no green and no amber, and
   inventing one for a success state is how palettes die. */

.panel {
  margin-top: var(--s-4);
  padding: var(--s-4);
  border: var(--bd-panel) solid var(--ink);
}
.panel--error { border-color: var(--red); }
.panel__title { margin-bottom: var(--s-2); }
.panel[hidden] { display: none; }


/* ---- Legal hub sub-navigation -------------------------------
   Terms, Privacy and Security are siblings, so they carry a
   shared sub-nav rather than sitting as orphans — the pattern
   Ghost uses for its policy set (Task 2 findings). */

.subnav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-4);
  margin-top: var(--s-4);
  font-size: var(--fs-nav);
  letter-spacing: var(--ls-nav);
  text-transform: uppercase;
  font-weight: 600;
}

.subnav a { color: var(--ink-soft); }        /* AA: --ink-faint is 3.14:1 */

/* The legal set's sub-nav is three 13px links. On touch they get the
   same 44px row every other tappable thing gets. */
@media (max-width: 899.98px) {
  .subnav a { display: flex; align-items: center; min-height: 44px; }
  .subnav { gap: 0 var(--s-4); }
}
.subnav a:hover { color: var(--red); }
.subnav a[aria-current="page"] {
  color: var(--ink);
  border-bottom: var(--bd-panel) solid var(--red);
  padding-bottom: 2px;
}


/* ---- Closing CTA, subpage rendition ------------------------- */

.page-closing {
  position: relative;
  padding: var(--s-7) var(--gutter);
  border-bottom: 0;
}

.page-closing__inner {
  position: relative;
  max-width: 1120px;
}

.page-closing__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
  margin-top: var(--s-5);
}


/* ---- 404 ----------------------------------------------------
   The ordinal voice at statement scale. The number is the
   page's one display element. */

.err {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 72vh;
  padding: var(--s-7) var(--gutter);
}

.err__code {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(72px, 16vw, 180px);
  line-height: .84;
  letter-spacing: var(--ls-hero);
  color: var(--red);
}

.err__title { margin-top: var(--s-4); }
.err__lead  { margin-top: var(--s-4); max-width: 52ch; }

.err__links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-4);
  margin-top: var(--s-5);
  font-size: var(--fs-nav);
  letter-spacing: var(--ls-nav);
  text-transform: uppercase;
  font-weight: 600;
}
.err__links a { border-bottom: var(--bd-panel) solid var(--red); padding-bottom: 3px; }

/* The recovery links are the only thing on a 404 worth tapping, so on
   touch they get the 44px row the rest of the site's links get. */
@media (max-width: 899.98px) {
  .err__links { gap: 0 var(--s-4); }
  .err__links a { display: flex; align-items: center; min-height: 44px; }
}


/* ---- Build-stage notice -------------------------------------
   Marks a page whose content lands in Task 3. It is deliberately
   loud: a quiet placeholder is one that ships. Delete the block
   and this rule together when the page is written. */

.wip {
  margin-top: var(--s-4);
  padding: var(--s-3);
  border: var(--bd-panel) dashed var(--red);
  font-size: 15px;
  line-height: 1.5;
  color: var(--ink-soft);
  /* It is prose, so it takes a prose measure — the page head's 1120px field
     would run it to ~150 characters a line. */
  max-width: 68ch;
}

.wip code {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--ink);
}
.wip strong { color: var(--red); }


/* ============================================================
   RESPONSIVE
   Six widths are checked: 1440, 1024, 768, 390, 360, 320.
   Sets collapse before they crush; nothing overflows sideways.
   ============================================================ */

@media (max-width: 1099.98px) {
  .cards--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cards--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 899.98px) {
  .page-head { padding-top: var(--s-6); }
  .cards { margin-top: var(--s-6); }
}

@media (max-width: 599.98px) {
  .cards,
  .cards--2,
  .cards--3,
  .cards--4 { grid-template-columns: minmax(0, 1fr); }

  .prose h2 { font-size: 26px; }
  .faq__q   { font-size: 19px; }

  /* A two-column spec table cannot hold its shape at phone
     widths: the header row goes away and each row becomes a
     labelled block. */
  .spec--stack thead { display: none; }
  .spec--stack tr {
    display: block;
    padding: var(--s-2) 0;
    border-bottom: var(--bd-hair) solid var(--rule);
  }
  .spec--stack th,
  .spec--stack td {
    display: block;
    padding: 0;
    border: 0;
  }
  .spec--stack td { margin-top: 6px; }
}

/* 360 and 320 are mandatory checks, not optional ones. At these
   widths the gutter is already at its 24px floor, so what has to
   give is the display type and the steps' rail inset. */
@media (max-width: 399.98px) {
  .install { padding-left: var(--s-4); }
  .install__step::before {
    left: calc((var(--s-4) * -1) - 5px + (var(--bd-rail) / 2));
  }
  .code { padding: var(--s-2); }
  .code pre { font-size: 13px; }
  .panel { padding: var(--s-3); }
  .faq__a { padding-left: 0; }
}


/* ---- Drawn figures -----------------------------------------
   The diagrams on the subpages are inline SVG, sized by the
   column rather than by their own viewBox. The intrinsic
   width/height attributes stay on the element so the box is
   reserved before paint (CLS), and this rule scales it. */

.figure__svg {
  width: 100%;
  height: auto;
}

.figure__svg--inset { margin-top: var(--s-4); }


/* ---- Narrow-width display type ------------------------------
   The subpage headlines are longer than the home page's — "Self-
   hosting is a real commitment." against "Docs. Cited. Yours." —
   and they are authored with a <br> that composes the desktop
   line break. Both facts break at phone widths: the <br> forces a
   line the viewport cannot hold, and a 12-character word in the
   44px H2 floor measures ~306px against 312px of content at 360.

   So below 560px the <br> stops applying and the H2 floor goes
   fluid. This mirrors what the home page already does for
   --fs-h2-xl at 460px, and for the same reason — the display
   floor is a composition rule, not a physical constant, and the
   words win when the two disagree. Scoped to :not(.cine-page)
   so the cinematic home page keeps its own measured values. */

@media (max-width: 599.98px) {
  html:not(.cine-page) {
    --fs-h2:    clamp(34px, 9.5vw, 76px);
    --fs-h2-lg: clamp(34px, 9.5vw, 84px);
    --fs-h2-xl: clamp(34px, 9.5vw, 92px);
  }

  /* The authored break is desktop composition; at this width the
     line has to find its own end. */
  .page-head__title br { display: none; }
}


/* ---- Legal review marker ------------------------------------
   Marks a clause that a lawyer has to sign off before the page
   goes live. Deliberately loud and deliberately inline with the
   clause it applies to — a review note at the top of the page
   tells you a review is needed; this tells you exactly WHERE.

   Every one carries data-legal-todo, so the whole set is one
   grep away:  grep -rn "TODO-LEGAL-REVIEW" .

   Delete the block and this rule together when the clause is
   approved. */

.legal-todo {
  display: block;
  margin: var(--s-3) 0;
  padding: var(--s-3);
  border: var(--bd-panel) dashed var(--red);
  background: var(--paper);
  font-size: 15px;
  line-height: 1.5;
  color: var(--ink-soft);
}

.legal-todo__tag {
  display: block;
  margin-bottom: var(--s-1);
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--fs-caption);
  letter-spacing: var(--ls-caption);
  text-transform: uppercase;
  color: var(--red);
}

/* The clause the marker guards, so the eye pairs them. */
.legal-pending {
  border-left: var(--bd-rail) solid var(--red);
  padding-left: var(--s-3);
}


/* ---- Diagram arrangements -----------------------------------
   A drawn diagram cannot simply be scaled into a phone. The
   architecture figure's labels measure 15.7px at 1440 and 4.8px
   at 390 — the same drawing, unreadable. So the wide row and the
   stacked column are two arrangements of the same content, and
   the viewport picks one. Same reasoning as the hero's two photo
   crops: shape changes, subject does not. */

.figure__svg--tall { display: none; }

@media (max-width: 599.98px) {
  .figure__svg--wide { display: none; }
  .figure__svg--tall { display: block; }
}


/* ---- Prose after a heading or lead --------------------------
   .prose sets margins BETWEEN its own children but carried none
   of its own, so where it follows a section heading or a lead
   the two collided — "Self-hosting is a real commitment." sat
   directly on top of the paragraph under it, with no gap at all.
   Visible on every split section; worst on a phone, where the
   column is narrow and the two run together as one block. */

.section__title + .prose,
.page-section__title + .prose,
.lead + .prose,
.page-section__lead + .prose { margin-top: var(--s-4); }


/* ---- Stacked splits: the figure follows the headline ---------
   Below 900px a split collapses to one column, and the question is
   where the drawing goes.

   DESIGN-NOTES put it after the argument — correct on a desktop,
   where the two sit side by side and the eye takes them as one
   spread. Stacked, they are not a spread: the drawing landed under
   a long block of text as an afterthought.

   The first fix for that was `order: -1` on the aside, which hoisted
   the drawing above the WHOLE argument — eyebrow and headline
   included. That is worse, and it is what "the images come above the
   text" was describing: the reader meets an unlabelled abstract
   drawing with nothing yet to tell them what it is of.

   The instinct was right and the unit was wrong. What should lead is
   the headline; the figure belongs directly under it, where an
   illustration sits under a chapter title and above the body. So the
   argument column dissolves (display: contents) and its children are
   ordered around the aside:

       eyebrow -> headline -> figure -> body

   display: contents removes only the box. The DOM is untouched, so
   every margin and every `title + prose` adjacency inside the column
   still resolves exactly as it does on a desktop — which is why the
   split's own gap has to go to zero here: spacing is the column's
   business, not the row's.

   Cards are deliberately excluded — a callout ("No GPU required") is
   a footnote to the argument and belongs after it. This only touches
   asides whose content is a drawing. */

@media (max-width: 899.98px) {

  .split:has(> .split__aside .figure__svg),
  .split:has(> .split__aside > .r-pop) { gap: 0; }

  .split:has(> .split__aside .figure__svg) > .split__main,
  .split:has(> .split__aside > .r-pop) > .split__main { display: contents; }

  /* Body copy last; the two chrome elements are lifted above the
     figure by name. Anything the column gains later falls to 4 and
     lands after the drawing, which is the safe default. */
  .split:has(> .split__aside .figure__svg) > .split__main > *,
  .split:has(> .split__aside > .r-pop) > .split__main > * { order: 4; }

  .split:has(> .split__aside .figure__svg) > .split__main > .eyebrow,
  .split:has(> .split__aside > .r-pop) > .split__main > .eyebrow { order: 1; }

  .split:has(> .split__aside .figure__svg) > .split__main > .display,
  .split:has(> .split__aside > .r-pop) > .split__main > .display { order: 2; }

  .split__aside:has(.figure__svg),
  .split__aside:has(> .r-pop) {
    order: 3;
    /* The row gap is gone, so the plate states its own breathing
       room — tighter above, where it is answering the headline,
       than below, where the body starts a new thought. */
    margin-top: var(--s-5);
    margin-bottom: var(--s-6);
  }

  /* A drawing that sits under a title needs to look deliberate
     rather than dropped: it takes the full column and its caption
     centres under it, like a plate. */
  .split__aside:has(.figure__svg) .caption,
  .split__aside:has(> .r-pop) .caption { text-align: center; }
}


/* ---- Tablets keep the spread --------------------------------
   sections.css collapses every split to one column below 1100px.
   That is right for a phone and wasteful for a wide tablet, so the
   spread is restored for one band.

   The band used to start at 760px, and that was the bug behind
   "tablets look bad". The reasoning was that the heading's widest
   word ("Sources", 183px) fits a 381px column — but fitting the
   longest word is not the readability test. Measured at 768px the
   argument column was 374px carrying a 44px display headline: four
   or five characters to the line, which reads as broken rather than
   as typeset.

   So the band now starts at 900px, where the argument column is
   ~500px and a 44px headline has somewhere to go. Below that it
   stacks, which is what a 768px tablet actually wants. */

@media (min-width: 900px) and (max-width: 1099.98px) {
  /* The display floors are authored for a full-width desktop column
     and only went fluid below 600px, so the whole tablet band was
     getting desktop-sized type in a two-thirds column. The floor is
     a composition rule, not a physical constant — in the band it
     tracks the viewport like every other size does. */
  :root {
    --fs-h2:    clamp(34px, 4.6vw, 76px);
    --fs-h2-lg: clamp(36px, 4.9vw, 84px);
    --fs-h2-xl: clamp(38px, 5.2vw, 92px);
  }

  /* The gap has to come out of the basis or the row wraps and you get
     the stacked layout back with none of the warning. 58% + 38% + a
     32px gap is 100.4% of a 691px tablet — four tenths of a percent,
     and the whole thing collapses. Subtracting the gap from ONE side
     makes the arithmetic exact: (60% - gap) + gap + 40% = 100%. */
  .split__main,
  .split__main--wide {
    flex: 1 1 calc(60% - var(--split-gap));
    max-width: none;
  }

  .split__aside,
  .split__aside--narrow {
    flex: 0 1 40%;
    max-width: 40%;
  }
}


/* ============================================================
   PAGE HEAD — THE PLATE
   The picture is the head's whole ground, held far back, the
   way the home hero's is.

   It has been three arrangements, and the first two were both
   trying to keep the image OUT of the copy's way — first a
   right-fading mask, then an explicit right-hand panel. Both
   worked by geometry, and geometry is the wrong tool here: it
   made every new photograph a fitting problem (the FAQ notepad
   sat at 32-65% and vanished entirely inside the first mask),
   and it capped the copy to a column to keep the two apart.

   Held back far enough, none of that is necessary. The image
   covers the head, the words sit anywhere on it, and no crop
   has to be tuned to anything.

   HOW FAR BACK IS MEASURED, NOT PICKED. --plate-o is the
   largest opacity at which the LEAD still clears 6:1 against
   the darkest 2% of that particular photograph — comfortably
   past the 4.5:1 AA floor, on the worst pixels rather than the
   average ones. The two pages differ because the pictures do:
   the FAQ frame is a dark warm brown (mean luminance 134), the
   hosting render is near-white (216).
   ============================================================ */

.page-head--plate { overflow: hidden; }

.page-head__plate {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

.page-head__plate picture,
.page-head__plate img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 50%;
}

/* Measured ceilings, one per photograph. The floor moved from 6:1 to 5:1 —
   still comfortably past the 4.5:1 AA minimum, and worth about a 55% lift in
   how present each picture is, which is what "a little more opacity" wanted.

   The three figures are far apart because the pictures are: features is a
   near-white studio render whose DARKEST 2% is still light peach, so it can
   carry half strength; the FAQ frame is warm brown and cannot. Raising one
   past its figure puts the lead under 5:1 on that image's worst pixels — so
   re-measure rather than nudge. */
.page-head--features { --plate-o: .52; }  /* darkest 2%: rgb(171,145,146) */
.page-head--hosting  { --plate-o: .26; }  /* darkest 2%: rgb( 46, 55, 73) */
.page-head--faq      { --plate-o: .22; }  /* darkest 2%: rgb( 11, 21, 24) */

.page-head--plate .page-head__inner { position: relative; z-index: 1; }

/* It arrives with the head rather than being simply present. */
.js .page-head__plate {
  opacity: 0;
  transition: opacity 1s var(--ease) 100ms;
}
.js .page-head__plate img {
  transform: scale(1.04);
  transition: transform 1.6s var(--ease) 100ms;
}
.js .page-head--plate.in .page-head__plate { opacity: var(--plate-o, .15); }
.js .page-head--plate.in .page-head__plate img { transform: none; }

/* No JS: the ground is simply there. */
html:not(.js) .page-head__plate { opacity: var(--plate-o, .15); }

@media (max-width: 899.98px) {
  /* The portrait crop, and a touch further back again: a phone shows more of
     the picture behind less text, so the same opacity reads stronger. */
  .page-head--features { --plate-o: .42; }
  .page-head--hosting  { --plate-o: .21; }
  .page-head--faq      { --plate-o: .18; }
}

@media (prefers-reduced-motion: reduce) {
  /* opacity 1 here would have shown the photograph at full strength — the one
     value it must never take. It is the measured ceiling, without the fade. */
  .js .page-head__plate { opacity: var(--plate-o, .15); transition: none; }
  .js .page-head__plate img { transform: none; transition: none; }
}
