/* The order form's own look — option D, "Editorial", picked 2026-08-31.
 *
 * WHY THIS FILE EXISTS RATHER THAN AN EDIT TO app.css. `app.css` is the shell
 * BOTH web pages wear and is shared with Lane L; restyling the order form in
 * it would restyle the landing page's shell with it. So the order page gets
 * its own stylesheet, exactly as `/` has `landing-hero.css`, and `app.css` is
 * untouched. See docs/parallel-sessions.md.
 *
 * ============================================================
 * EVERY RULE HERE NAMES `.orderpage` TWICE, AND THAT IS LOAD-BEARING.
 * ============================================================
 *
 * `{% block head %}` is line 24 of `base.html.j2`; `app.css` is linked on line
 * 43. So a stylesheet linked the way the landing page links its own loads
 * BEFORE app.css, and every rule here would lose the cascade to an app.css
 * rule of equal specificity — silently, and only for the properties app.css
 * happens to set, which is the worst shape a styling bug can take.
 *
 * The landing page does not hit this because it renames everything: its
 * selectors are `.lh-*` and collide with nothing. This page keeps `.field`,
 * `.hint` and `.cta`, because the markup is shared with the form's own tests
 * and its script. So the cascade is won on SPECIFICITY instead of order:
 * `.orderpage.orderpage .field input` is 0-3-1 against app.css's 0-1-1.
 *
 * This is trap 1 from `docs/design-mockups.md` — "a rule naming one class
 * loses silently" — arriving in production rather than in a mock-up. The
 * design page proved the rules; this is what it costs to ship them.
 *
 * The class sits on the form's own `<section>` in `order.html.j2`, so the
 * whole look is opted into in one place and reverted by deleting one word.
 * `body.orderpage-page.orderpage-page, body:has(.orderpage)` is how the ground is reached from here, which is the
 * same mechanism `landing-hero.css` uses in `body:has(.lh)`.
 *
 * --- the palette, copied from the landing page, not imported ---------------
 *
 * These are `landing-hero.css`'s values as of 2026-08-31. COPIED on purpose:
 * that file is Lane L's, and importing its tokens would mean a change over
 * there silently redraws this page. Two pages agreeing is worth more than two
 * pages coupled.
 *
 * THE ACCENT IS NOT A BUTTON COLOUR. White on #b3892f is 2.6:1 — the landing
 * page only ever uses it for a 6px dot, which is decoration and exempt from
 * the contrast minimum. A CTA is 15px text and needs 4.5:1, so the button is
 * INK (15.9:1 on paper), which is what the landing page's own buttons do.
 * #8a6620 is the accent's text-safe twin at 5.2:1 and carries the one tinted
 * line — "required", and the suggestion note.
 */

/* ON THE BODY TOO (2026-09-04), because three rules in this file are written
   `body.orderpage-page.orderpage-page, body:has(.orderpage) … var(--op-…)` and a custom property declared on the
   section is not visible from its ancestor: `var()` there is invalid at
   computed-value time, which for `background` means TRANSPARENT and for
   `color` means inherit. Measured in Chrome: the page's ground computed
   rgba(0,0,0,0) — the paper this file has claimed since 2026-08-31 was the
   canvas's white — and the beta bar's accent word was plain ink. Declaring
   the tokens where those rules can see them is the fix; the rules themselves
   were right. */
body.orderpage-page.orderpage-page, body:has(.orderpage), .orderpage {
  --op-paper: #faf9f6;
  --op-ink: #141414;
  --op-ink-muted: rgba(20, 20, 20, .62);
  --op-hair: rgba(20, 20, 20, .16);
  --op-hair-light: rgba(20, 20, 20, .1);
  /* THE CONTROL BOUNDARY IS NOT A HAIRLINE, and this is the one value that
     departs from the landing page's palette. `landing-hero.css` has
     `--lh-hair-strong` at .28, where it draws RULES BETWEEN SECTIONS —
     decoration, and exempt. Here the same line is the ONLY thing marking where
     a field is, because option D takes the boxes off. WCAG 1.4.11 asks 3:1 of
     anything needed to identify a control, and .28 measures 1.86:1 on paper.
     .48 measures 3.23:1 and is what ships; .46 is the floor at 3.04:1, and the
     margin is deliberate because it composites over paper rather than being a
     flat value.

     FOR THE RECORD, THE SHELL WAS WORSE: app.css draws its box in #E4E7EC on
     #F8F9FB, which is 1.18:1. This is not a regression that arrived with the
     redesign, it is one the redesign was measured for. */
  --op-hair-strong: rgba(20, 20, 20, .48);
  --op-band: #f3f2ef;
  --op-accent: #b3892f;
  --op-accent-text: #8a6620;
  --op-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
             Helvetica, Arial, sans-serif;
}

/* THE GROUND. `body:has()` rather than a class on `<body>`, because `<body>`
   belongs to `base.html.j2` and this lane does not edit that file. 0-1-1
   against app.css's `body` at 0-0-1, so it wins on specificity and does not
   depend on load order — unlike everything below it. */
body.orderpage-page.orderpage-page, body:has(.orderpage) { background: var(--op-paper); }

.orderpage.orderpage {
  font-family: var(--op-sans);
  color: var(--op-ink);
}

.orderpage.orderpage h1 {
  font-family: var(--op-sans);
  font-weight: 600;
  letter-spacing: -.022em;
  font-size: 30px;
  line-height: 1.15;
  color: var(--op-ink);
  margin: 0 0 10px;
}

.orderpage.orderpage .lede {
  font-size: 15.5px;
  line-height: 1.55;
  color: var(--op-ink-muted);
  max-width: 54ch;
}

/* --- the rows ------------------------------------------------------------
 *
 * Label and hint left, control right, a hairline under each row. The form
 * reads as a table of decisions rather than a stack of boxes, which is the
 * whole of what "D" was.
 *
 * THE CONTROL SPANS BOTH ROWS. Without `grid-row: 1 / span 2` the control
 * takes row 1 and the hint takes row 2 UNDERNEATH it, so every row becomes
 * label + control + hint stacked and the two-column layout comes out TALLER
 * than the single column it replaced. Measured on the design page: 1517px
 * against 1234px before this line existed, 1314px after.
 *
 * WHAT IT COSTS, because it is visible and was not in the stylesheet: where a
 * hint is longer than its control — Region is the worst — the row's height
 * comes from the LEFT column and leaves space under the input on the right.
 * That is the trade this layout makes, and the fix is shorter hints rather
 * than more CSS. Flagged to the operator rather than papered over.
 */
.orderpage.orderpage .order {
  border-top: 1px solid var(--op-hair);
  margin-top: 30px;
}

.orderpage.orderpage .field {
  display: grid;
  /* 300px RATHER THAN 240, and it is the lever that fixes every row at once.
     The dead space this layout leaves under a control comes from the left
     column wrapping; widening it wraps less. Measured across the eight rows at
     900px: 240px left Region 119px of dead space, website 65, country 49,
     competitors 47, other names 47. The control column loses 60px and does not
     miss it — every control is full-width and the shortest of them still runs
     past 300px. */
  grid-template-columns: 300px 1fr;
  gap: 0 40px;
  align-items: start;
  padding: 22px 0;
  margin: 0;
  border-bottom: 1px solid var(--op-hair-light);
}

.orderpage.orderpage .field label {
  grid-column: 1;
  grid-row: 1;
  display: block;
  margin: 0;
  padding-top: 8px;
  font-family: var(--op-sans);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--op-ink-muted);
}

.orderpage.orderpage .req {
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  color: var(--op-accent-text);
}

/* CONTROLS LOSE THEIR BOXES. The shell draws a 1px box on four sides; this
   draws one line under the place to type. That line is then the ONLY thing
   identifying the control, which is why `--op-hair-strong` is heavier here
   than the landing page's equivalent — see the note on it above. */
.orderpage.orderpage .field input,
.orderpage.orderpage .field select,
.orderpage.orderpage .field textarea {
  grid-column: 2;
  grid-row: 1 / span 2;
  align-self: start;
  width: 100%;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--op-hair-strong);
  border-radius: 0;
  padding: 7px 2px;
  font: inherit;
  font-size: 16px;
  color: var(--op-ink);
  transition: border-color .12s ease;
}

/* --- a field the prefill left blank (2026-09-02) --------------------------
 *
 * `order.js` puts `.needs-you` on the category's `.field` when the prefill
 * filled other rows and left this one empty. The row's underline is the only
 * thing this page gives a control, so the underline is what carries the mark.
 *
 * NOT `--op-accent`, WHICH IS THE OBVIOUS CHOICE AND IS BACKWARDS. Measured on
 * paper: #b3892f is 3.05:1 and `--op-hair-strong` is 3.23:1 — so painting the
 * accent here would draw the marked field in a LIGHTER line than the nine
 * unmarked ones beside it, and the field being pointed at would recede. That
 * is invisible in code and invisible in a screenshot until you measure it.
 * `--op-accent-text` (#8a6620) is 4.98:1 and is already this page's "this one
 * needs you" colour — it carries `.req` and the suggestion line.
 *
 * WEIGHT STAYS AT 1px so FOCUS IS STILL VISIBLE. Focus is 2px in the accent;
 * a 2px mark would leave a marked field looking identical focused and not,
 * which trades one accessibility failure for another.
 *
 * IT SITS ABOVE `:hover` AND `:focus` ON PURPOSE. All three are 0-4-1, so the
 * cascade is decided by ORDER here, and the transient states must win — a
 * field that stops responding to hover because it is marked is worse than an
 * unmarked one. This is the same trap the header of this file is about, one
 * rule further in.
 */
.orderpage.orderpage .field.needs-you input {
  border-bottom-color: var(--op-accent-text);
}

.orderpage.orderpage .field input:hover,
.orderpage.orderpage .field select:hover,
.orderpage.orderpage .field textarea:hover {
  border-bottom-color: var(--op-ink);
}

/* The focus ring is the underline thickening in the accent rather than an
   outline box, and the padding gives back the pixel the border takes so the
   control does not shift under the cursor. */
.orderpage.orderpage .field input:focus,
.orderpage.orderpage .field select:focus,
.orderpage.orderpage .field textarea:focus {
  outline: 0;
  border-bottom: 2px solid var(--op-accent);
  padding-bottom: 6px;
}

/* The one control that keeps a box: a textarea is a REGION, and an underlined
   region has no bottom edge to speak of until you have typed into it. */
.orderpage.orderpage .field textarea {
  border: 1px solid var(--op-hair);
  border-radius: 2px;
  padding: 10px 12px;
  background: #fff;
  line-height: 1.55;
}
.orderpage.orderpage .field textarea:focus {
  border: 1px solid var(--op-accent);
  padding: 10px 12px;
}

.orderpage.orderpage .field input::placeholder,
.orderpage.orderpage .field textarea::placeholder {
  color: var(--op-ink-muted);
}

/* THE HINT SITS UNDER THE LABEL, NOT UNDER THE CONTROL. In two columns a hint
   below the input pushes the next row down by its own height and the rows stop
   lining up — which is the layout falling apart rather than a nicety. */
.orderpage.orderpage .hint {
  grid-column: 1;
  grid-row: 2;
  margin: 6px 0 0;
  font-size: 12px;
  line-height: 1.5;
  color: var(--op-ink-muted);
}

/* The suggestion lines are the exception and belong beside the control they
   are about — the category note under the category, the prefill note under the
   brand. Both are `role=status`; a live region announcing from the far column
   reads as being about the wrong field. */
/* ROW 3, NOT ROW 2 (fixed 2026-09-02). The control spans `1 / span 2`, so row
   2 is UNDER THE INPUT rather than after it: a suggestion placed there was
   drawn straight through the field's own underline. Measured on the category
   row at 1920px — input 271.5→310.5, note starting at 301.5, NINE PIXELS of
   overlap, with the note's first line sitting exactly on the rule.

   It is pre-existing and was rare: the only thing that wrote a suggestion was
   the website→category path, which needs a typed website. The blank-category
   mark put it on the screen of everyone arriving from the landing page, which
   is how it was finally seen. `#brand-suggestion` had it too and is fixed by
   the same line.

   Row 3 is implicit and only exists while a note does, so an ordinary row is
   the height it always was. Nothing below 720px is affected — `.field` is
   `display: block` there and every grid placement in this file is inert. */
.orderpage.orderpage .field .suggestion {
  grid-column: 2;
  grid-row: 3;
  align-self: start;
  margin-top: 8px;
  color: var(--op-accent-text);
}

/* --- "which company is this?" (2026-09-02) --------------------------------
 *
 * A one-word brand name identifies nobody, so `brand_prefill` hands back the
 * host it found as a QUESTION rather than filling the website in. This is the
 * question, and it sits under the brand field in the control's own column.
 *
 * ROW 4, because row 3 is `.suggestion` and the brand field uses both: the
 * status line says "Check which company this is." and this asks it. The
 * control still spans rows 1-2 — see the note on `.suggestion` for why
 * anything placed under a control has to clear that span.
 *
 * IT IS THE `.errors` TREATMENT, not a new one: band, and a 2px accent rule
 * down the left. This page already means "stop and read this" with that
 * shape, and a form that invents a second vocabulary for its second
 * interruption teaches the reader nothing. `--op-accent` is decoration here —
 * a 2px edge, not text — which is the one use its 3.05:1 is exempt for.
 */
.orderpage.orderpage .confirm {
  /* BOTH COLUMNS, unlike everything else placed under a control. Measured at
     1568px: in the control column alone the question wrapped to three lines
     and the two buttons stacked, because that column is 245px. It is also the
     wrong SHAPE — this is not an annotation on a field, it is the form
     stopping to ask something, which is what `.errors` looks like and why it
     borrows that treatment. Full width, and the buttons sit side by side. */
  grid-column: 1 / -1;
  grid-row: 4;
  align-self: start;
  margin-top: 10px;
  background: var(--op-band);
  border-left: 2px solid var(--op-accent);
  padding: 12px 14px;
}

.orderpage.orderpage .confirm-q {
  margin: 0 0 10px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--op-ink);
}

.orderpage.orderpage .confirm-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

/* Smaller than `.cta` on purpose: this is a question inside a form, not the
   form's own action, and a second button the size of "Run my report" competes
   with it. Ink on paper for the answer that proceeds, a hairline for the one
   that does not — the same weighting the page gives its primary button. */
.orderpage.orderpage .confirm-btn {
  font-family: var(--op-sans);
  font-size: 13px;
  line-height: 1.2;
  padding: 8px 14px;
  border-radius: 2px;
  border: 1px solid var(--op-ink);
  background: var(--op-ink);
  color: #fff;
  cursor: pointer;
}

.orderpage.orderpage .confirm-btn-quiet {
  background: transparent;
  color: var(--op-ink);
  border-color: var(--op-hair-strong);
}

.orderpage.orderpage .confirm-btn:hover { background: #000; border-color: #000; color: #fff; }
.orderpage.orderpage .confirm-btn-quiet:hover {
  background: transparent;
  color: var(--op-ink);
  border-color: var(--op-ink);
}

/* THE FOCUS RING IS DRAWN, NOT INHERITED. Everything else on this form shows
   focus by thickening its underline, and these have no underline to thicken —
   without this rule a keyboard user tabbing into the question sees nothing at
   all. `outline-offset` keeps it clear of the ink button's own edge. */
.orderpage.orderpage .confirm-btn:focus-visible {
  outline: 2px solid var(--op-accent-text);
  outline-offset: 2px;
}

.orderpage.orderpage .cta {
  margin-top: 28px;
  background: var(--op-ink);
  color: #fff;
  border: 1px solid var(--op-ink);
  border-radius: 2px;
  padding: 12px 26px;
  font-family: var(--op-sans);
  font-size: 15px;
  font-weight: 500;
  letter-spacing: .01em;
}
.orderpage.orderpage .cta:hover { background: #000; border-color: #000; color: #fff; }
.orderpage.orderpage .cta:focus-visible {
  outline: 2px solid var(--op-accent);
  outline-offset: 2px;
}


.orderpage.orderpage .errors {
  background: var(--op-band);
  border: 0;
  border-left: 2px solid var(--op-accent);
  border-radius: 0;
  padding: 14px 18px;
}
.orderpage.orderpage .errors-head { color: var(--op-ink); }

/* --- narrow ---------------------------------------------------------------
 *
 * TWO COLUMNS NEED THE WIDTH AND DO NOT GET IT ON A PHONE. Below 720px every
 * row goes back to a single column — label, control, hint — which is option B
 * from the design page and is a layout this form has always had. `display:
 * block` releases every grid-column and grid-row above it in one line.
 *
 * The 16px font-size on the controls is NOT a style choice and must not be
 * reduced: iOS Safari zooms in on a field under 16px and does not zoom back
 * out. That is why the whole form went to 16px on 2026-08-30.
 */
@media (max-width: 720px) {
  .orderpage.orderpage .field {
    display: block;
    padding: 18px 0;
  }
  .orderpage.orderpage .field label { padding-top: 0; margin-bottom: 7px; }
  .orderpage.orderpage .hint { margin-top: 7px; }
  .orderpage.orderpage .field .suggestion { margin-top: 8px; }
}

/* --- stage one: one field, and it should look like one -------------------
 *
 * `order.js` adds `.staged` while the form is folded behind the brand name,
 * and removes it when the rest arrives. Everything below therefore describes a
 * state a visitor with no scripts never enters — which is why it is keyed off
 * a class the script adds rather than off a media query or the markup.
 *
 * WHAT IT FIXES, seen rather than reasoned (2026-08-31, on request). The
 * two-column layout is a TABLE OF DECISIONS and it needs rows to be one. With
 * a single row it read as a fragment of a table: `BRAND` hard left, the input
 * hard right, ~300px of nothing between them, and a hairline above AND below
 * one field floating in an otherwise empty page. Every rule here is about
 * making one field look like one field.
 */
.orderpage.orderpage .order.staged {
  border-top: 0;
  margin-top: 26px;
}

.orderpage.orderpage .order.staged .field {
  display: block;
  padding: 0;
  border-bottom: 0;
}

.orderpage.orderpage .order.staged .field label {
  padding-top: 0;
  margin-bottom: 10px;
}

/* THE ONE FIELD IS THE PAGE'S SUBJECT NOW, so it is set at the size of one.
   18px against the form's 16 — enough to read as the thing being asked for,
   and still over the 16px floor that stops iOS zooming in and never zooming
   back out. NEVER take this below 16. */
.orderpage.orderpage .order.staged .field input {
  font-size: 18px;
  padding: 10px 2px;
}

.orderpage.orderpage .order.staged .hint {
  margin-top: 9px;
}

/* The button sits under the field it belongs to rather than a table's worth of
   rows away. */
.orderpage.orderpage .order.staged .cta {
  margin-top: 22px;
}

/* --- stage one's button --------------------------------------------------
 *
 * It is the ONLY thing to do on the page at that moment, so it is allowed more
 * presence than the shell's flat rectangle. Scoped to `#prefill-go` rather
 * than `.cta`: the submit button in stage two sits under a long form and does
 * not want a shadow lifting it off the page, and the two are never on screen
 * together, so they do not have to match.
 *
 * STILL INK, NOT THE ACCENT — white on #b3892f is 2.6:1 and this is 15.5px
 * text. The gold appears as a hairline under the button instead, where it is
 * decoration and exempt, and where it is the one warm mark on a black shape.
 */
.orderpage.orderpage #prefill-go {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 14px 30px;
  font-size: 15.5px;
  border-radius: 3px;
  border-bottom: 2px solid var(--op-accent);
  box-shadow: 0 1px 2px rgba(20, 20, 20, .14), 0 6px 18px rgba(20, 20, 20, .10);
  transition: transform .14s ease, box-shadow .14s ease, background-color .14s ease;
}

/* The arrow leans out on hover. One property, 3px, and it reads as the button
   pointing at what happens next rather than as an animation. */
.orderpage.orderpage #prefill-go .cta-arrow {
  display: inline-block;
  font-size: 17px;
  line-height: 1;
  transition: transform .16s ease;
}

.orderpage.orderpage #prefill-go:hover {
  transform: translateY(-1px);
  box-shadow: 0 2px 4px rgba(20, 20, 20, .18), 0 10px 26px rgba(20, 20, 20, .14);
}
.orderpage.orderpage #prefill-go:hover .cta-arrow { transform: translateX(3px); }

/* Pressed puts it back down. A button that lifts and never lands feels stuck. */
.orderpage.orderpage #prefill-go:active {
  transform: translateY(0);
  box-shadow: 0 1px 2px rgba(20, 20, 20, .16);
}

.orderpage.orderpage #prefill-go:focus-visible {
  outline: 2px solid var(--op-accent);
  outline-offset: 3px;
}

/* MOTION IS OPTIONAL AND THE INFORMATION IS NOT. Everything above moves; the
   colour, the shadow and the arrow all stay, so a reader who has asked for
   less motion loses nothing but the movement. */
@media (prefers-reduced-motion: reduce) {
  .orderpage.orderpage #prefill-go,
  .orderpage.orderpage #prefill-go .cta-arrow { transition: none; }
  .orderpage.orderpage #prefill-go:hover { transform: none; }
  .orderpage.orderpage #prefill-go:hover .cta-arrow { transform: none; }
}

/* --- the prompts box -----------------------------------------------------
 *
 * What a client is paying for, shown rather than described. A `<details>`
 * because it is genuinely secondary — most people will order without opening
 * it — and because it needs no script to open.
 */
.orderpage.orderpage .prompts {
  margin: 4px 0 26px;
  padding: 0 0 4px;
  border-bottom: 1px solid var(--op-hair-light);
}

.orderpage.orderpage .prompts > summary {
  cursor: pointer;
  padding: 14px 2px;
  /* Larger than a hint and larger than the group names it opens onto, because
     it is the one line inviting somebody into the box at all — and the box is
     the only place a client can see what they are paying for. Still under the
     15.5px of the form's own controls: it opens a section, it is not a field. */
  font-size: 15px;
  font-weight: 500;
  color: var(--op-ink);
  list-style-position: outside;
}
.orderpage.orderpage .prompts > summary:hover { color: var(--op-accent-text); }
.orderpage.orderpage .prompts > summary:focus-visible {
  outline: 2px solid var(--op-accent);
  outline-offset: 2px;
}

.orderpage.orderpage .promptlist {
  margin: 6px 0 14px;
  padding: 0 0 0 26px;
  counter-reset: none;
}

/* Each row is the question and, under it, the one thing the words cannot say:
   whether an answer counts toward the visibility score. */
.orderpage.orderpage .promptrow {
  margin: 0 0 14px;
  padding: 0;
}

.orderpage.orderpage .promptbox {
  width: 100%;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--op-hair);
  border-radius: 0;
  padding: 6px 2px;
  font: inherit;
  font-size: 15px;
  color: var(--op-ink);
}
.orderpage.orderpage .promptbox:hover { border-bottom-color: var(--op-hair-strong); }
.orderpage.orderpage .promptbox:focus {
  outline: 0;
  border-bottom: 2px solid var(--op-accent);
  padding-bottom: 5px;
}

/* --- one group per category ---------------------------------------------
 *
 * The box is read as "what kinds of question is this?" before "which
 * fourteen?", so the categories are the first thing open and the questions sit
 * inside them. Nested `<details>` rather than a script: it opens with no JS,
 * keeps its state per group, and is keyboard-operable for free.
 */
.orderpage.orderpage .promptgroup {
  border-top: 1px solid var(--op-hair-light);
}
.orderpage.orderpage .promptgroup:last-of-type {
  border-bottom: 1px solid var(--op-hair-light);
}

.orderpage.orderpage .promptgroup > summary {
  display: flex;
  align-items: baseline;
  gap: 10px;
  cursor: pointer;
  padding: 12px 2px;
  font-size: 14px;
}
.orderpage.orderpage .promptgroup > summary:hover .groupname { color: var(--op-accent-text); }
.orderpage.orderpage .promptgroup > summary:focus-visible {
  outline: 2px solid var(--op-accent);
  outline-offset: 2px;
}

/* NOT BOLD (2026-08-31, on request). Five bold rows down the box read as
   five headings competing with the summary above them; the arrow and the
   ink already say these are the things to open. */
.orderpage.orderpage .groupname { font-weight: 400; color: var(--op-ink); }

/* THE DISCLOSURE MARK, and it is ours rather than the browser's: a `<summary>`
   set to `display: flex` loses its native triangle in Chrome, so a group would
   otherwise look like a heading and not like something that opens. The same
   arrow the Continue button uses — one glyph, one meaning, twice on the page.
   It turns a quarter when the group is open. */
.orderpage.orderpage .groupmark {
  display: inline-block;
  font-size: 14px;
  line-height: 1;
  color: var(--op-ink-muted);
  transition: transform .16s ease, color .16s ease;
}
.orderpage.orderpage .promptgroup[open] > summary .groupmark {
  transform: rotate(90deg);
  color: var(--op-accent-text);
}
.orderpage.orderpage .promptgroup > summary:hover .groupmark { color: var(--op-accent-text); }

/* The native marker goes with it, or a group shows two. */
.orderpage.orderpage .promptgroup > summary { list-style: none; }
.orderpage.orderpage .promptgroup > summary::-webkit-details-marker { display: none; }

@media (prefers-reduced-motion: reduce) {
  .orderpage.orderpage .groupmark { transition: none; }
}

/* THE ONE THING THE WORDING CANNOT SAY: whether an answer to this kind of
   question counts toward the visibility score. A question that NAMES the brand
   cannot — an answer mentioning it has demonstrated nothing — and that rule
   belongs where a reader meets the questions, not only in the methodology
   footer. 11.5px, so `--op-ink-muted` at 5.07:1 rather than anything lighter. */
.orderpage.orderpage .groupwhy {
  margin-left: auto;
  font-size: 11.5px;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--op-ink-muted);
  text-align: right;
}

.orderpage.orderpage .groupblurb { margin: 0 0 10px 2px; }

@media (max-width: 620px) {
  /* Stacked, or the group name and its note fight for one line on a phone. */
  .orderpage.orderpage .promptgroup > summary { flex-wrap: wrap; }
  .orderpage.orderpage .groupwhy { margin-left: 0; flex-basis: 100%; text-align: left; }
}

/* In the two-column layout the box spans BOTH columns: it is not a labelled
   field, it is a section, and squeezing fourteen questions into the control
   column would set them at half the width of the form. */
@media (min-width: 721px) {
  .orderpage.orderpage .prompts { grid-column: 1 / -1; }
}

/* STAGE ONE'S LINE IS THE PROPOSITION, so it is set like one (2026-08-31, on
   request). 20px against the form's 15.5 — a deck under the heading rather
   than a paragraph in the form, which is what it is: the only sentence on the
   page at the moment somebody is deciding whether to bother.
   `#the-lede`, the long one, is deliberately NOT changed. It is three lines of
   explanation beside a filled-in form, and 20px would make it shout. */
.orderpage.orderpage #stage-one-say {
  font-size: 20px;
  line-height: 1.4;
  letter-spacing: -.008em;
  /* 30ch stranded "competitors." on a line of its own. 46ch is the sentence,
     so it sits on one line where there is room; `balance` splits it evenly
     where there is not, rather than leaving one word alone. Unsupported
     browsers get ordinary wrapping, which is what this had before. */
  max-width: 46ch;
  text-wrap: balance;
  margin-bottom: 4px;
}

/* On a phone the deck gives back a little, or it takes four lines of a small
   screen before the field it is introducing. */
@media (max-width: 480px) {
  .orderpage.orderpage #stage-one-say { font-size: 18px; }
}

/* --- while it is looking something up -------------------------------------
 *
 * `order.js` sets `.is-working` on the button and on the note beside the brand
 * field for as long as a lookup is in flight.
 *
 * THE DISABLING IS THE POINT AND THE SPINNER IS THE COURTESY. A button that
 * still looks pressable during a two-second lookup gets pressed again, and a
 * visitor reads an unchanged page as nothing having happened. The script also
 * refuses a second lookup outright — `disabled` stops the click, but Enter in
 * the name field calls the same function directly.
 */
.orderpage.orderpage #prefill-go[disabled] {
  cursor: default;
  opacity: .72;
  /* No lift, no shadow growth, no arrow slide: nothing that says "press me". */
  transform: none;
  box-shadow: 0 1px 2px rgba(20, 20, 20, .14);
}
.orderpage.orderpage #prefill-go[disabled] .cta-arrow { transform: none; }

/* The arrow becomes the spinner rather than sitting beside one — one mark in
   the button, doing one job at a time. */
.orderpage.orderpage #prefill-go.is-working .cta-arrow {
  width: 13px;
  height: 13px;
  color: transparent;          /* the glyph goes; the ring takes its place */
  border: 2px solid rgba(255, 255, 255, .32);
  border-top-color: #fff;
  border-radius: 50%;
  animation: op-spin .7s linear infinite;
}

/* THE NOTE GETS A DIFFERENT MARK, NOT A SECOND RING. Both were spinning
   circles at first, six inches apart, and two of the same mark for one state
   is a repeated signal rather than a clearer one. The button keeps the ring
   because the ring is ON the control it disables; the note gets a line that
   sweeps under the words, which says "still going" in a way nothing else on
   the page is saying.

   `::after` is decoration and carries no text, so nothing is announced that a
   screen reader would have to skip — the note itself is `role=status` and
   reads "Looking up …" aloud already. */
.orderpage.orderpage #brand-suggestion.is-working::after {
  content: "";
  display: block;
  width: 100%;
  max-width: 220px;
  height: 2px;
  margin-top: 8px;
  border-radius: 2px;
  background-image: linear-gradient(
    90deg, transparent 0%, var(--op-accent) 50%, transparent 100%
  );
  background-size: 55% 100%;
  background-repeat: no-repeat;
  /* 1.6s, up from 1.15 (2026-08-31, on request). A sweep that crosses quickly
     reads as urgency; this one is telling somebody to wait a couple of seconds
     while four services are asked, so it should look unhurried. Slower than
     the button's ring on purpose — the ring marks a control, the line marks a
     wait, and they are not the same tempo. */
  animation: op-sweep 1.6s ease-in-out infinite;
}

@keyframes op-spin { to { transform: rotate(360deg); } }
@keyframes op-sweep {
  0%   { background-position: -60% 0; }
  100% { background-position: 160% 0; }
}

/* MOTION IS OPTIONAL; THE STATE IS NOT. With reduced motion the rings stop
   turning and stay as rings — still visibly different from the resting state,
   still beside a note that says what is happening in words, and the button is
   still disabled, which was always the load-bearing half. */
/* MOTION IS OPTIONAL; THE STATE IS NOT. The ring stops turning and stays a
   ring; the sweep stops moving and stays a line, centred so it reads as a rule
   under the note rather than as a bar caught halfway. Both remain visibly
   different from the resting state, the note still says what is happening in
   words, and the button is still disabled — which was always the load-bearing
   half. */
@media (prefers-reduced-motion: reduce) {
  .orderpage.orderpage #prefill-go.is-working .cta-arrow,
  .orderpage.orderpage #brand-suggestion.is-working::after {
    animation: none;
  }
  .orderpage.orderpage #brand-suggestion.is-working::after {
    background-position: 50% 0;
  }
}

/* --- compact enough that the button is above the fold --------------------
 *
 * Asked for on 2026-08-31: "Run my report" was 334px below the fold at an
 * 813px viewport, so nobody saw the thing they came to press without
 * scrolling past six fields first.
 *
 * THE HEIGHT WAS IN THE LEFT COLUMN, not in the controls. Every row is as tall
 * as its label-plus-hint, and three of the hints wrapped to four lines at
 * 300px. So the column gets wider and the hint gets smaller — which shortens
 * rows without taking a single word off the page. The padding comes down with
 * it; 22px of air per row is generous for a form of six.
 */
.orderpage.orderpage .field {
  /* 380px: the width at which every hint but one fits two lines. Measured, not
     chosen — at 300 three of them wrapped to four lines and each wrapped line
     is a row taller. The control column keeps ~400px at the form's width,
     which is more than any control here needs. */
  grid-template-columns: 380px 1fr;
  gap: 0 32px;
  padding: 8px 0;
}
.orderpage.orderpage .field label { padding-top: 4px; }
.orderpage.orderpage .hint {
  margin-top: 4px;
  font-size: 11.5px;
  line-height: 1.45;
}
.orderpage.orderpage .order { margin-top: 18px; }
.orderpage.orderpage h1 { font-size: 26px; margin-bottom: 6px; }
.orderpage.orderpage #the-lede { font-size: 14.5px; margin-bottom: 0; }
.orderpage.orderpage .prompts { margin: 2px 0 14px; }
.orderpage.orderpage .prompts > summary { padding: 10px 2px; }
.orderpage.orderpage .cta { margin-top: 12px; }

/* === STAGE ONE IS CENTRED (option C, picked 2026-09-01) ===================
 *
 * `/order` was reported as bland, and it was: since the staged flow shipped
 * the first screen has been a heading, one line, one field and a button on a
 * page nine hundred pixels tall, laid out by rules written for a table of
 * eight rows. This owns the emptiness rather than filling it.
 *
 * IT IS STAGE ONE ONLY, AND THAT IS THE WHOLE DIFFICULTY WITH THIS OPTION.
 * Centred is right for one field and wrong for eight: at stage two a centred
 * heading over eight left-aligned rows reads as a mistake. So `order.js` puts
 * `stage-one` on the WRAPPER while the form is folded and takes it off when
 * the rest arrives — one element further out than `.staged`, because the
 * heading and the lede are outside the form.
 *
 * The design page called this out before it was picked: "the only option that
 * gets WORSE at stage two". This block is the answer to that, and every rule
 * in it is inside `.stage-one`. Nothing here reaches the full form.
 */
.orderpage.orderpage.stage-one {
  max-width: 620px;
  margin: 0 auto;
  text-align: center;
  padding-top: 52px;
}

.orderpage.orderpage.stage-one h1 {
  font-size: 34px;
  letter-spacing: -.028em;
  line-height: 1.12;
}

.orderpage.orderpage.stage-one #stage-one-say {
  margin: 0 auto 28px;
  /* 46ch, matching the rule this one overrides. 34ch broke the sentence at
     "AI names / you or your competitors" — mid-phrase, and worse centred than
     it is left-aligned, because both ragged edges are then visible. */
  max-width: 46ch;
}

/* THE LABEL AND THE HINT GO. With one field on a centred page, "BRAND
   required" above it and "The brand the report is about" below it are three
   labels for one box — the heading has already said what the page is for and
   the placeholder says what to type. They come back with the rest of the form,
   where eight fields genuinely need telling apart.
   The `<label>` is still in the markup and still bound to the input, so it is
   still what a screen reader announces; only its rendering goes. */
.orderpage.orderpage.stage-one .order.staged .field label,
.orderpage.orderpage.stage-one .order.staged .hint { display: none; }

/* A REAL BOX, not the underline. The underline belongs to a table of rows and
   there is no table here; on its own, centred, it reads as a rule with text
   above it rather than as somewhere to type. 19px is well over the 16px floor
   that stops iOS zooming in and never zooming back out. */
.orderpage.orderpage.stage-one .order.staged .field input {
  /* THE BOX IS CENTRED; THE TEXT IN IT IS NOT. Centring the text put the caret
     at the middle of an empty field — which is exactly where the centred
     placeholder already sits, so the cursor blinked in the middle of the word
     "brand". Visible the moment `autofocus` landed and invisible in the CSS
     before that. Left is also what every hero field of this shape does: the
     box is the thing that is centred. */
  text-align: left;
  /* 22px in an 18px-padded box (2026-09-01, on request). At stage one this is
     the only control on the page and the page's whole subject, so it is set
     like one rather than like the first of nine. Well over the 16px floor that
     stops iOS zooming in and never zooming back out. */
  font-size: 22px;
  padding: 18px 16px;
  background: #fff;
  border: 1px solid var(--op-hair);
  border-radius: 8px;
}
.orderpage.orderpage.stage-one .order.staged .field input:hover {
  border-color: var(--op-hair-strong);
}
.orderpage.orderpage.stage-one .order.staged .field input:focus {
  border: 1px solid var(--op-accent);
  padding: 18px 16px;          /* the border does not change width, so no shift */
  box-shadow: 0 0 0 3px rgba(179, 137, 47, .16);
}

.orderpage.orderpage.stage-one .order.staged { margin-top: 22px; }

/* Full width under the field it belongs to, rather than a small button adrift
   in the middle of a centred column. */
.orderpage.orderpage.stage-one #prefill-go {
  width: 100%;
  justify-content: center;
  padding: 15px 26px;
  margin-top: 14px;
}

/* The note keeps its own alignment: `text-align: center` on the wrapper would
   otherwise centre a sentence that is read left-to-right beside a field. */
.orderpage.orderpage.stage-one #brand-suggestion {
  text-align: center;
  margin-top: 14px;
}
.orderpage.orderpage.stage-one #brand-suggestion.is-working::after {
  margin-left: auto;
  margin-right: auto;
}

@media (max-width: 620px) {
  .orderpage.orderpage.stage-one { padding-top: 34px; }
  .orderpage.orderpage.stage-one h1 { font-size: 28px; }
}

/* --- ADVANCED FEATURES: the optional fields, collapsed (2026-09-03) --------
 *
 * The five optional fields sit under one disclosure so the form opens on the
 * two required ones. A native <details>, styled to read as a section the way
 * `.prompts` below does, not as a field. The `.advanced-label` and its
 * `.advanced-sub` give the summary a title and a one-line list of what is
 * inside, so a client knows what they are opening before they open it.
 */
.orderpage.orderpage .advanced {
  margin: 4px 0 22px;
  border: 1px solid var(--op-hair-light);
  border-radius: 10px;
  padding: 0 16px;
}
.orderpage.orderpage .advanced[open] {
  padding-bottom: 8px;
}
.orderpage.orderpage .advanced > summary {
  cursor: pointer;
  padding: 15px 2px;
  list-style: none;               /* the default triangle off; a chevron below */
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
}
.orderpage.orderpage .advanced > summary::-webkit-details-marker { display: none; }
/* A chevron drawn from a border, rotated when open — no image, no dependency. */
.orderpage.orderpage .advanced > summary::before {
  content: ""; flex: none; width: 7px; height: 7px;
  border-right: 2px solid var(--op-accent-text);
  border-bottom: 2px solid var(--op-accent-text);
  transform: rotate(-45deg); transition: transform .15s ease;
  position: relative; top: -2px;
}
.orderpage.orderpage .advanced[open] > summary::before {
  transform: rotate(45deg);
}
.orderpage.orderpage .advanced-label {
  font-size: 15px; font-weight: 500; color: var(--op-ink);
}
.orderpage.orderpage .advanced-sub {
  font-size: 12.5px; color: var(--op-ink-muted);
}
.orderpage.orderpage .advanced > summary:hover .advanced-label { color: var(--op-accent-text); }
.orderpage.orderpage .advanced > summary:focus-visible {
  outline: 2px solid var(--op-accent); outline-offset: 2px; border-radius: 6px;
}
/* The first field inside gains a little air from the summary. */
.orderpage.orderpage .advanced[open] > .field:first-of-type { margin-top: 4px; }

/* --- PANELS (2026-09-04, option D of design/order-layouts.html, on request) ---
 *
 * The form as three white panels on the band ground: the two required fields
 * in one, the optional five behind "Advanced features" in a second, the
 * questions in a third. Chosen from six layouts drawn over the real page;
 * the mock-up's D showed both boxes OPEN and the request was D with both
 * SHUT, which is what this is — the summaries stay real disclosure controls
 * and keep their chevrons, styled as the panels' headings.
 *
 * APPENDED, NOT EDITED IN PLACE, and the cascade is the mechanism: every rule
 * here is at least the specificity of the rule it overrides and comes later
 * in the file, which is what lets the earlier blocks stay as the record of
 * how each piece came to be. Measured afterwards in a real Chrome — the
 * panel's fill and border, the box's padding, the summary's size — rather
 * than trusted, per docs/design-mockups.md.
 *
 * WHAT STAYS OUT. Stage one (`.order.staged`) is one centred field and gets
 * no panel: the `:not(.staged)` below is that exclusion, and the panel
 * arrives with the rest of the form. The beta bar is shared with the landing
 * page and is untouched; the ground behind it changes, the bar does not.
 */
body.orderpage-page.orderpage-page, body:has(.orderpage) { background: var(--op-band); }

.orderpage.orderpage .order {
  border-top: 0;
  margin-top: 26px;
}

/* The required pair: one panel, two rows, the radius split across them. */
.orderpage.orderpage .order:not(.staged) > .field,
.orderpage.orderpage #the-rest > .field {
  background: #fff;
  border: 1px solid var(--op-hair);
  border-bottom: 0;
  padding: 20px 24px;
  grid-template-columns: 240px 1fr;
}
.orderpage.orderpage .order:not(.staged) > .field:first-child {
  border-radius: 10px 10px 0 0;
}
.orderpage.orderpage #the-rest > .field {
  border-radius: 0 0 10px 10px;
  border-bottom: 1px solid var(--op-hair);
  margin-bottom: 20px;
}

/* The two boxes: panels with a heading that opens them. */
.orderpage.orderpage .advanced,
.orderpage.orderpage .prompts {
  background: #fff;
  border: 1px solid var(--op-hair);
  border-radius: 10px;
  padding: 2px 24px 4px;
  margin: 0 0 20px;
}
.orderpage.orderpage .advanced[open],
.orderpage.orderpage .prompts[open] {
  padding-bottom: 12px;
}
.orderpage.orderpage .advanced > summary,
.orderpage.orderpage .prompts > summary {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  cursor: pointer;
  list-style: none;
  padding: 16px 0 14px;
  font-size: 16px; font-weight: 600; color: var(--op-ink);
}
.orderpage.orderpage .prompts > summary::-webkit-details-marker { display: none; }
/* The same chevron on both, so one glyph means "this opens" for both panels. */
.orderpage.orderpage .prompts > summary::before {
  content: ""; flex: none; width: 7px; height: 7px;
  border-right: 2px solid var(--op-accent-text);
  border-bottom: 2px solid var(--op-accent-text);
  transform: rotate(-45deg); transition: transform .15s ease;
  position: relative; top: -2px;
}
.orderpage.orderpage .prompts[open] > summary::before { transform: rotate(45deg); }
.orderpage.orderpage .advanced[open] > summary,
.orderpage.orderpage .prompts[open] > summary {
  border-bottom: 1px solid var(--op-hair-light);
}
.orderpage.orderpage .advanced-label { font-size: 16px; font-weight: 600; }
/* The list of what is inside, on its own line under the heading, aligned
   with it past the chevron. */
.orderpage.orderpage .advanced-sub {
  flex: 1 0 100%;
  margin: -6px 0 0;
  padding-left: 17px;
}
.orderpage.orderpage .prompts > .hint { margin: 12px 0 4px; }

/* Rows inside a panel keep their hairlines and lose the panel's own edge. */
.orderpage.orderpage .advanced > .field,
.orderpage.orderpage .prompts .field {
  padding: 20px 0;
  border-bottom: 1px solid var(--op-hair-light);
}
.orderpage.orderpage .advanced > .field:last-of-type { border-bottom: 0; }
.orderpage.orderpage .promptgroup:last-of-type { border-bottom: 0; }
.orderpage.orderpage .advanced[open] > .field:first-of-type { margin-top: 0; }

.orderpage.orderpage .order:not(.staged) .cta { margin-top: 6px; }

@media (prefers-reduced-motion: reduce) {
  .orderpage.orderpage .prompts > summary::before { transition: none; }
}

/* NO WRAP ON THE QUESTIONS SUMMARY (QA, 2026-09-04). It is one line of text
   after a chevron, and with `flex-wrap` inherited from the shared rule above
   a 320px screen broke the TEXT onto a second line and left the chevron
   alone on the first. The advanced summary keeps wrapping — its sub-line
   and its note are meant to drop under the heading. */
.orderpage.orderpage .prompts > summary { flex-wrap: nowrap; }

/* THE FOOTER ON THE BAND (QA, 2026-09-04). The shell's `.foot` is `--faint`
   (#667085), which is 4.9:1 on white and 4.44:1 on this page's band —
   under the 4.5 AA asks of 12.5px text. The page's own muted ink measures
   4.97:1 here. Scoped to this page; the shell's rule is untouched. */
body.orderpage-page.orderpage-page, body:has(.orderpage) .foot { color: var(--op-ink-muted); }

/* On a phone the panels give back their side padding, or a 390px screen
   spends 48px of every row on white space. */
@media (max-width: 620px) {
  .orderpage.orderpage .order:not(.staged) > .field,
  .orderpage.orderpage #the-rest > .field {
    padding: 16px 16px;
  }
  .orderpage.orderpage .advanced,
  .orderpage.orderpage .prompts {
    padding-left: 16px;
    padding-right: 16px;
  }
}

/* --- 2026-09-05, six follow-ups from the design pass ---------------------- */

/* 2. Stage one's placeholder, and ONLY stage one's: once the form is
   revealed the label and hint are back and the grey text would be the third
   thing describing the box. Painted out rather than removed, because the
   markup is one attribute and the staging is the script's. */
.orderpage.orderpage .order:not(.staged) #brand::placeholder { color: transparent; }

/* 3. The placed website beside the brand — the landing's chip: white pill,
   the stronger hairline, 11.5px, muted. Under the hint, in the label
   column; on a phone it flows after the input. */
.orderpage.orderpage .site-chip {
  grid-column: 1;
  grid-row: 3;
  justify-self: start;
  margin-top: 8px;
  padding: 3px 9px;
  border-radius: 999px;
  background: #fff;
  border: 1px solid var(--op-hair-strong);
  font-size: 11.5px;
  line-height: 1.4;
  font-weight: 500;
  color: var(--op-ink-muted);
}

/* 4. The questions read as text until touched. Fourteen underlined boxes
   read as fourteen fields to fill; the underline now appears on hover and
   the accent rule on focus, so a question is a sentence that turns into a
   field when somebody reaches for it. The inputs are unchanged. */
.orderpage.orderpage .promptbox { border-bottom-color: transparent; cursor: text; }
.orderpage.orderpage .promptbox:hover { border-bottom-color: var(--op-hair); }

/* 5. The line under the button. */
.orderpage.orderpage .fineprint {
  margin-top: 12px;
  font-size: 12.5px;
  color: var(--op-ink-muted);
}

/* 1 + 6. One working ring for both buttons. The arrow span is EMPTY at rest
   and draws nothing; while a button is working it becomes the ring, on the
   Continue button as before and now on "Run my report" too, which is
   disabled by the script the moment it is pressed. */
.orderpage.orderpage .cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
}
.orderpage.orderpage .cta .cta-arrow:empty { display: none; }
.orderpage.orderpage .cta.is-working .cta-arrow:empty {
  display: inline-block;
  width: 13px;
  height: 13px;
  border: 2px solid rgba(255, 255, 255, .32);
  border-top-color: #fff;
  border-radius: 50%;
  animation: op-spin .7s linear infinite;
}
.orderpage.orderpage .cta[disabled] {
  cursor: default;
  opacity: .72;
  transform: none;
}
@media (prefers-reduced-motion: reduce) {
  .orderpage.orderpage .cta.is-working .cta-arrow:empty { animation: none; }
}

/* --- a question we reworded for this trade (2026-09-06) -----------------
   `web/question_style.py` offers the library's questions back in the brand's
   own trade — "Is CBS a good TV network?" for "Is CBS any good?". The box is
   the same one a person types in, so the only thing to draw is that this one
   did not come from them, and a way back.

   DOUBLED, like every rule in this file: `order.css` loads BEFORE `app.css`,
   so document order is against us and a single class loses. */
.orderpage.orderpage .promptrow.is-reworded {
  position: relative;
}
/* A HAIRLINE, NOT A FILL. Fourteen rows and up to nine of them reworded: a
   tint on each would read as nine warnings rather than nine suggestions. The
   mark says "this one is ours to offer", which is the quietest thing on the
   row and should stay that way. */
.orderpage.orderpage .promptrow.is-reworded .promptbox {
  box-shadow: inset 2px 0 0 var(--op-accent, #B8791A);
}
.orderpage.orderpage .rewordback {
  margin-left: 8px;
  border: 0;
  background: none;
  padding: 2px 4px;
  font: inherit;
  font-size: 12.5px;
  color: var(--op-ink-muted, #6A6F76);
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}
.orderpage.orderpage .rewordback:hover,
.orderpage.orderpage .rewordback:focus-visible {
  color: var(--op-ink, #20242A);
}

/* --- a question this order does not ask (2026-09-07) --------------------
   The box shows fourteen questions and the run asks twelve when no region is
   typed: `{region}` cannot be filled, so `build_prompts` skips those two.
   Until this rule they were on the page anyway, with a literal "{region}" in
   them, under a heading that says these are the questions we will ask.

   HIDDEN AND DISABLED, in `order.js` — see the note there for why the row is
   the unit. This rule is only the hiding half; a row that is display:none but
   still posting is the defect one layer down. */
.orderpage.orderpage .promptrow.is-unasked { display: none; }

/* THE PROMPT EDITORS ZOOM ON iOS, AND THE RULE THAT STOPS IT COULD NOT REACH
   THEM (2026-09-07, found by a phone sweep of the whole site).

   `app.css` already carries `@media (pointer: coarse) { .field input, .field
   select, .field textarea { font-size: 16px } }` — Safari zooms the page when a
   focused field is under 16px and does not zoom back out, so every field the
   reader can type into has to be 16px on a touch device. Its own comment says
   it covers "the order form's ten fields", and it does. There are FOURTEEN
   more.

   The prompt editors are not among the ten because they are not inside a
   `.field`: they live in `.promptrow` inside `.promptlist` inside
   `<details class="prompts">`, a list that is closed when the page loads and
   only exists once the reader opens it. So the selector misses them —
   `promptbox.closest('.field')` is null — and they stayed at 15px. One pixel
   under the threshold, on the fourteen fields a reader is most likely to be
   editing at length.

   HERE RATHER THAN IN `app.css`, for specificity: these inputs are styled as
   `.orderpage.orderpage .promptbox` (0-3-0, the doubled class is this file's
   way of outranking the shell), which a `.field input` rule at 0-2-1 loses to
   even where it matches. Same file, same specificity, later in source order.

   `pointer: coarse` and not a width, for the reason app.css gives: a phone in
   landscape is 844 or 932 across and Safari zooms there just the same, so a
   width breakpoint switches the fix off in the orientation where sideways
   scrolling hurts most. */
@media (pointer: coarse) {
  .orderpage.orderpage .promptbox { font-size: 16px; }
}

/* AND THE SAME FLOOR ON THE FORM'S OWN CONTROLS (2026-09-07).

   Measured at 390: the seven text fields draw 39px, the country select 35px
   and the fourteen prompt editors 36px. The submit button is already 44 and
   does not move. Same reasoning as the font-size rule above and the same
   `pointer: coarse` condition: this is a fingertip question, not a width one.

   The select is the one worth naming. At 35px it was the smallest control on
   the page and it is the one control a reader cannot correct by tapping again
   in a slightly different place — a mis-tap opens the native picker on the
   wrong row, or does not open it at all. */
@media (pointer: coarse) {
  .orderpage.orderpage .field input,
  .orderpage.orderpage .field select,
  .orderpage.orderpage .promptbox {
    min-height: 44px;
  }
}

/* THE SUBMIT BUTTON STAYS ON SCREEN ON A PHONE (2026-09-08).

   Reported with a screenshot: "Run my report" sat at the very bottom edge,
   half under the browser's own toolbar, on a form whose two required fields
   were already filled in.

   THE MEASUREMENT THAT EXPLAINS IT, and why the desktop numbers looked fine.
   At a nominal 390x844 the button is at 719 and ends at 763, comfortably
   inside 844 — so any check against the DEVICE height says it fits. What a
   phone actually gives a page is far less: Chrome on iOS spends something like
   150-190px on the address bar and the toolbar, so the usable viewport is
   nearer 660, and 763 is well past it. The button was below the fold on every
   phone while measuring as though it were not.

   STICKY RATHER THAN MOVED ABOVE THE OPTIONAL SECTIONS, which was the other
   candidate. Moving it would put the submit control before the advanced fields
   and the question editor in DOM ORDER, so a keyboard user would reach Submit
   and then continue tabbing into more inputs — the form's own order is right
   and worth keeping. Sticky changes where it is DRAWN, not where it is.

   FULL WIDTH WITH A PAD OF PAPER AROUND IT. A 155px button stuck to the bottom
   would let the form scroll past on either side of it, which reads as a
   floating fragment rather than a bar; the ring of `--op-paper` gives it a
   ground, and the width doubles as a bigger target on the surface where
   targets matter. The form gains bottom padding so the last card can still be
   scrolled clear of it.

   `pointer: coarse`, as everywhere else in this file: this is about a browser
   that spends a third of the screen on its own furniture and a thumb that
   needs the control to be reachable, not about how wide the window is. */
@media (pointer: coarse) {
  .orderpage.orderpage #order-submit {
    position: sticky;
    bottom: 14px;
    z-index: 5;
    width: 100%;
    box-shadow: 0 0 0 14px var(--op-paper), 0 6px 18px rgba(20, 20, 20, .12);
  }
  .orderpage.orderpage .order { padding-bottom: 20px; }
}
