/*
 * THE QUESTION-TYPE EDITOR'S CHROME — the type tag, the popover, the config sub-card and
 * the option rows that public/js/question-types.js builds.
 *
 * ── IT WAS 889 LINES OF JAVASCRIPT UNTIL 2026-09-17 ─────────────────────────────────
 * `ensureStyles()` concatenated these 86 rules as a string and appended a <style> at
 * DOM-ready. The audit's §6 D-5 called it "a whole stylesheet mirrored in JS" and §7 F-2
 * called its position a fragility: the injected sheet landed after every <link>, so it
 * won four selectors it collides on by source order alone. This is the audit's P8.
 *
 * [HARD] THE LINK MUST BE LAST, AND "LAST" IS NOT "IN start.blade.php's HEAD PUSH".
 * `@push('styles')` appends in RENDER order, and `facilitator/_manage-chrome.blade.php`
 * pushes manage-chrome.css from the page's BODY — measured on a manage render, the link
 * order is …setup-page, auth-modal, setup-page-render-even, manage-chrome, plan-locks.
 * So this file is pushed from the END of start.blade.php's `@section('content')`, after
 * every partial has rendered, which is the only position that reproduces what appending
 * at DOM-ready produced. `App\Support\SetupPageSource::ownCssPaths()` asserts it: it is
 * the last entry in OWN_CSS and the order is checked against the page's own <link> lines.
 *
 * MOVING THIS LINK EARLIER SILENTLY REVERTS FOUR RULES. They are named in the decision
 * record entry "question-types.css leaves the JavaScript, and four collisions are
 * resolved (2026-09-17)"; three of them were resolved by deleting the loser, so today
 * only the cascade of the remaining overlaps depends on this position.
 *
 * THE EXTRACTION IS PROVED, NOT ASSERTED. The browser was driven, the injected
 * `#qt-styles` textContent was read off the live page, and the file below was generated
 * from the JavaScript source and compared against it: 9,554 bytes, byte-identical. Every
 * comment travelled with its rule.
 *
 * NOTHING HERE IS RUNTIME-COMPUTED, WHICH CORRECTS THE BRIEF. The plan expected
 * `--qcfg-field` and anything like it to stay in JS as a computed property. It is not
 * computed: `.qt-subcard{--qcfg-field:calc(240px + …)}` and its 100% phone arm are both
 * static declarations, `question-types.js` calls `setProperty` nowhere, and the whole
 * concatenation is literals. So the whole sheet moved and no rule was left injected.
 */
[data-question-wrap]{position:relative;}
[data-question-wrap] > .tpl-item-row > .tpl-item-input{flex:1 1 auto;min-width:0;}
.qt-tag-wrap{position:relative;display:inline-flex;flex-shrink:0;align-self:stretch;}
/* .qt-col-label and .qt-list-title DELETED here (P6c, 2026-09-18) — P1 leftovers from
   the standalone radio row (see .qt-correct-label below); no emitter anywhere. Do not
   re-add; docs/type-scale-proposal-2026-09-18.md §1.3. */
.qt-list-header{margin-bottom:8px;}
/* ── THE TYPE CONTROL IS A SPLIT TAG: A DARK CAP JOINED TO A LIGHT VALUE ──
   Two halves inside one <button>: .qt-tag-cap says WHAT THE CONTROL IS
   ("TYPE", on ink) and .qt-tag-value says WHAT IT IS SET TO (the type name
   and the caret, on white). The control had only ever shown its value, so
   it read as a state badge rather than as something you change; the cap is
   the half that was missing, and it is why the value half can now drop the
   rust outline it was using to say "I am a control".
  
   THE WHOLE SKIN LIVES HERE, AND THIS IS THE ONLY PLACE IT LIVES. Through
   2026-09-08 the paint was split: this sheet held a bordered grey chip, and
   start.blade.php out-specified all of it from `.tpl-start .qt-type-col
   .qt-tag` (0,3,0) — a page restating a component's own element, kept in
   step by nothing. start.blade.php is the ONLY view that loads this file
   (one <script> tag, verified by grep), so the page arm had no reach the
   component arm lacked; it was specificity spent on nothing. Those five
   rules are DELETED there, not overridden from here. If this control needs
   a new declaration, it goes in this block.
  
   TOKENS, and the two that are a step off the brief. --tpl-field-label is
   12px against the cap's specified 11, and --tpl-input-size is 16px against
   the value's 15.5 — the nearest existing tokens in each case, taken rather
   than minting a pair one pixel apart from tokens that already exist. The
   value now reads at the same tier as the field text under it, which is the
   right relationship for a control holding a stored string.
  
   ── THE TAG IS EXACTLY AS TALL AS THE ORDINAL BADGE BESIDE IT ────────────
   min-height reads --tpl-badge-size, which is where the badge's OWN height
   comes from: `.tpl-start .tpl-edit-row--header > [data-card-num], …` in
   start.blade.php sets `width`/`height`/`flex-basis` from that token, and
   `.tpl-start{--tpl-badge-size:var(--col-num-left)}` resolves it — 26px at
   >=641 and 24px at <=640. Read off the rendered page with
   CSS.getMatchedStylesForNode, not inferred: the badge also matches
   `.tpl-item-num{width:2rem}` (32px) and `.tpl-abel{font-size:18px}`, neither
   of which wins. So the two boxes share ONE source and the phone's smaller
   badge is followed without a second rule.
  
   min-height, NOT height, and the vertical padding is 0 rather than trimmed
   to arithmetic: the natural height is 18px (a 16px value line inside 1px
   borders), so the token governs at both widths — and a type name that ever
   wraps grows the tag instead of being clipped by a fixed box. Nothing here
   states 26 or 24. */
.qt-tag{box-sizing:border-box;display:inline-flex;align-items:stretch;
min-height:var(--tpl-badge-size);
padding:0;gap:0;border:1px solid var(--border-strong);border-radius:var(--radius-square);
background:var(--color-white);color:var(--color-text-primary);cursor:pointer;
text-align:left;font-family:var(--font-mono);line-height:var(--type-field-line);}
/* Uppercase is the CAP'S, in CSS. The lang string stays sentence case so it
   can be translated into a language that does not have this typographic
   convention, which is the same reason every other caption on this surface
   states its case rather than storing it.
  
   BOTH HALVES CARRY ZERO VERTICAL PADDING AND line-height:1, and the tag is
   align-items:stretch — so each half fills the tag's whole height and centres
   its own text inside it. The height is the tag's to state (above), never a
   half's: padding that adds up to a height puts the number in two places and
   makes the two halves disagree the moment either string changes size. */
.qt-tag-cap{flex:0 0 auto;display:flex;align-items:center;padding:0 11px;
background:var(--ink);color:var(--on-ink);font-family:var(--font-mono);
font-size:var(--tpl-field-label);letter-spacing:0.09em;line-height:var(--type-badge-line);
text-transform:uppercase;white-space:nowrap;}
/* ── THE VALUE READS AS THE RAIL'S TEMPLATE PICKER DOES (2026-09-17) ──────
   The three tokens below are the ones setup-sidebar.css gives
   `.tpl-sidebar .tpl-switcher-trigger-label` — the Template dropdown's value in
   the right rail — so this control subscribes to that treatment instead of
   naming Bebas Neue a second time. Measured before the change: that label is
   Bebas Neue / uppercase / 0.24px tracking, this value was DM Mono / none /
   normal.
  
   --font-heading, NOT --tpl-cardname-font, even though both resolve to Bebas
   here: the rail rule reads --font-heading, and the point is to read the same
   token it does. --tpl-cardname-font is the CARD NAME tier (a criterion name, a
   section name, the identity boxes) and this is not a member of it.
  
   THE SIZE IS DELIBERATELY NOT TAKEN. The rail rule pairs its face with
   --tpl-rail-label (12px) because it sits in a 248px rail; this tag sits on a
   question card's top line and keeps --tpl-input-size. Face, case and tracking
   are the treatment; the size is the context.
  
   .qt-tag-cap is untouched — the black TYPE half stays DM Mono — and so is
   .qt-popover below: the Template dropdown's OPEN MENU is not Bebas either
   (.tpl-menu is --font-mono and .tpl-switcher-item defers to it; measured
   DM Mono 12px), so matching it means leaving the type menu alone. */
.qt-tag-value{flex:1 1 auto;min-width:0;display:flex;align-items:center;
gap:var(--gap-row);padding:0 var(--inset-box);background:var(--color-white);color:var(--color-text-primary);
/* THE SIZE IS --tpl-kicker-size (14px), DOWN FROM --tpl-input-size (16px),
   2026-09-17. Not a literal and not a new token: --tpl-kicker-size is defined in
   tokens.css as exactly this step — the BEBAS size one below --tpl-input-size,
   chosen there because "Bebas runs small for its px" and a Bebas label at 16
   competes with the field text beside it. This value is Bebas and is a label for
   the card's type, so it is the same tier by construction rather than by
   coincidence.
  
   THE BOX DOES NOT MOVE. .qt-tag states min-height:var(--tpl-badge-size), so the
   control keeps the height it had; measured 26.00 x 177.0 at 1440 and 24.00 at
   375, unchanged. The black cap half keeps --tpl-field-label (12px) and its own
   tracking — untouched.
  
   CENTRING IS UNAFFECTED BY THE SIZE, which is the point of the mechanism that
   holds it: .qt-tag-label takes `text-box: trim-both cap alphabetic` in
   templates.css, so the box being centred is the ink at whatever size it is.
   Measured +0.59 before and after. */
font-family:var(--font-heading);
letter-spacing:var(--tpl-cardname-tracking, 0.02em);
text-transform:var(--tpl-cardname-case, uppercase);
font-size:var(--tpl-kicker-size);line-height:var(--type-card-name-line);}
/* The name wraps rather than truncating — the page's rule, and the reason
   the cap carries the nowrap instead. (This was `.tpl-start .qt-type-col
   .qt-tag-label` in start.blade.php; it moved here with the rest of the skin.) */
.qt-tag-label{min-width:0;white-space:normal;overflow-wrap:anywhere;}
/* Caret sized to the ROW-CONTROL glyphs (2026-08-02). 9px read as a faint
   smudge beside the label, and next to the 18px × / 16px ⧉ on the same row
   it looked like a rendering artefact rather than a control.
  
   16px, matching .qt-row-dup rather than the 18px ×, chosen not split: the two
   glyphs disagree (see D-DEBT-16), so one had to be picked. ⧉ is the closer
   analogue — both it and ▾ are geometric glyphs inside a button, where × is a
   text character that reads visually larger at the same px — and 16 is the
   smaller of an ambiguous pair. Unchanged by the split-tag rebuild: this is
   still the only size this glyph family takes on the surface.
  
   Muted INK, built from --ink-rgb, so the caret sits under the type name
   without introducing a second colour to the value half. (It used to declare
   no colour at all and inherit, which worked while the tag had an active/
   inactive colour pair; the value half is one colour now, so the caret has to
   say its own.)
  
   NOT GLOBAL ANY MORE IN PRACTICE, though the selector is unchanged: the note
   that stood here said the MS section-type control emitted this class too. It
   stopped doing that on 2026-08-29, when that control became a full-bleed tab
   strip with no popover and no caret. The per-question tag is the sole emitter. */
.qt-tag-caret{margin-left:auto;font-size:var(--type-field);line-height:var(--type-field-line);
color:var(--ink-glyph-muted);}
/* Hover is on the VALUE half only — the cap is a fixed label, so lighting it
   would say the cap is the thing being pointed at. Same wash .qt-popover-item
   uses, so the trigger and the menu it opens respond identically. */
.qt-tag:hover .qt-tag-value{background:var(--surface-warm-hover);}
/* Focus is stated on the TAG, not left to the UA ring on the button box: the
   tag is the hit area, so it has to be the focus area. outline-offset:2px puts
   the ring clear of the 1px ink border rather than doubling it. Same
   declaration as .tpl-panel-close (templates.css), the surface's other
   explicitly-focused control. */
.qt-tag:focus-visible{outline:2px solid var(--border-strong);outline-offset:2px;}
.qt-tag[disabled]{opacity:0.5;cursor:default;}
/* (a) Left-anchored to the trigger (drops straight below it) + viewport-capped
   so it can never spill off either edge. The old right:0 anchor grew the menu
   LEFTWARD from the trigger's right edge, which threw it off-screen once the
   mobile trigger became content-sized. Desktop is unaffected (its trigger is
   the same 190px as the menu, so left:0 and right:0 coincide). */
.qt-popover{position:absolute;top:calc(100% + 4px);left:0;right:auto;z-index:var(--z-popover);background:var(--color-white);border:1px solid var(--border-strong);min-width:190px;max-width:calc(100vw - 48px);box-shadow:var(--shadow-popover);display:flex;flex-direction:column;padding:var(--inset-tag);}
.qt-popover[hidden]{display:none;}
.qt-popover-item{background:none;border:none;text-align:left;padding:var(--inset-control) var(--gap-row);cursor:pointer;}
.qt-popover-item:hover{background:var(--surface-warm-hover);}
.qt-popover-item.active{color:var(--color-text-primary);background:rgba(var(--red-rgb),0.06);}
/* ── THE CONFIG PANEL HAS NO SKIN AND NO INDENT (2026-08-20) ─────────────
   It was a tinted, ink-bordered box inset by a whole marker column — a card
   inside the block, holding fields that are now parts of the block like any
   other. Every one of those declarations is DELETED rather than overridden:
   the fill, the border, the padding and the margin-left. What is left is a
   plain region of the pair, so its parts share the block's left and right edges
   with the name and the Instruction above them, which is what "one right edge"
   means. The class stays because --qcfg-field and the toggles resolve by it. */
.qt-subcard{background:none;border:0;margin:0;padding:0;}
/* .qt-subcard-label DELETED here (P6c, 2026-09-18) — no emitter anywhere; the
   "QUESTION N: … Options" captions this described render some other way now.
   Do not re-add; docs/type-scale-proposal-2026-09-18.md §1.3. */
/* ── THE TOGGLE LABEL NEEDS THE PAGE'S LABEL STEP ────────────────────────
   The weighting mode label sat at display:inline with no margin, so the
   segmented control it names started 21.5px ABOVE its own bottom edge —
   measured, not read: they were on one line, not stacked. Its sibling one
   row down ("Budget total", .tpl-crit-tag) is display:block with
   margin-bottom:10px, which is --step-tight, THE page's label-to-field
   step (setup-geometry.md: "A label states --step-tight as its own
   margin-bottom … part of the field it names, so it cannot strand"). This
   takes the same token so the two labels in this panel cannot disagree; no
   number is stated.
  
   A COMPONENT CLASS AND A COMPONENT RULE. The label keeps its page TIER
   (.tpl-mono + .tpl-workshop-mode-label, the "names a control you flip"
   tier) — that was never the defect — and the box change rides .qt-mode-label
   so this file still emits the page's classes and none of its rules. */
.qt-mode-label{display:block;margin-bottom:var(--step-tight);}
/* Config sub-area typography (task c). ALL inputs / selects / textareas in
   EVERY question-type config card take the canonical DM Mono 12px ink,
   uppercase — the single upstream rule (form controls don't inherit the
   container font, so target them here). This supersedes the per-field
   .tpl-abel font on config inputs. NOT added to .tpl-mono globally. */
.qt-subcard input,.qt-subcard select,.qt-subcard textarea{font-family:var(--font-mono);font-size:var(--tpl-field-label);color:var(--color-text-primary);text-transform:var(--tpl-config-case);}
/* Quiz per-option "correct" RADIO keeps the platform green accent
   (it's a radio, not a checkbox). Every CHECKBOX in the config UI
   (checklist "Include Don't Know", Hint, word-cloud mode) is
   standardised on a PLAIN box — accent-color:auto, checkmark only, no
   fill — via the single shared .qt-subcard-toggle input rule below. */
/* .qt-correct-label (this rule, its `input` child rule, and .qt-opt-row's own
   > .qt-correct-label layout rule below) DELETED here (P6c, 2026-09-18) — the
   standalone radio row it labelled is gone (question-types.js:963); no emitter
   anywhere, including the setup-page.css rules that still target it. Do not
   re-add; docs/type-scale-proposal-2026-09-18.md §1.3. */
/* ── Config sub-area row COMPONENTS (Patterns A–E) — one fluid layout per
      recurring row, keyed on real classes, correct at EVERY width (no
      desktop/mobile fork). These REPLACE the former mobile-only descendant
      patches in the @media block below (deleted in the same change).
   Pattern A — option row. Its OWN component (NOT .tpl-item-row), so it is no
   longer governed by the main item-row geometry (start.blade.php:628's fixed
   --col-line-width, which overflowed the narrow config panel). The input
   wrapper fills the row and shrinks so the × always stays in the card; quiz
   CORRECT wraps to its own line, aligned under the option input.
   An option row is a ROW IN THE BLOCK, laid out like DM's item rows: badge,
   field, trailing x. `margin-bottom:8px` is DELETED — the per-row distance is
   the config container's one structural rule, like every other part.
  
   ── V4 / V5: THE NESTED PAIR RESERVES ITS BADGE COLUMN, EXACTLY AS A TOP-LEVEL
      ROW DOES (2026-08-24) ──────────────────────────────────────────────────
   The option row IS the rule-bearing box (it is a .tpl-crit-part), and its rule
   used to run from the row's own edge — i.e. under the badge — while the option
   text started --col-nest-x further in. Same defect the top level had before the
   field inset moved into --col-line-x, one level down: an underline 36px to the
   left of the text it underlines.
  
   So the row starts at V5 and the badge is laid out INSIDE the column reserved in
   front of it, giving back exactly the advance it took. That is the same reserve
   idiom the drag gutter uses (see THE CARD-BADGE COLUMN in start.blade.php) —
   net advance zero, so the text after it is unmoved and only the rule's origin
   changes. Measured at 1280: badge stays 401 (V4), text stays 437 (V5), rule
   401 -> 437.
  
   [HARD] THE EMITTER STATES NO NUMBER HERE. --col-nest-x is declared in
   templates.css beside the other column tokens; this file reads it, as it reads
   --col-gap and --col-line-x. That is the boundary as the 2026-08-23 audit
   restated it (A.17.6): the emitter may WEAR the page's classes and READ its
   tokens, but may not query its selectors and may not invent a dimension. A 36px
   literal here would be inventing one. */
.qt-opt-row{display:flex;flex-wrap:wrap;align-items:center;gap:var(--col-gap);margin-left:var(--col-nest-x);}
.qt-opt-row > .tpl-item-num{margin-left:calc(-1 * var(--col-nest-x));}
.qt-opt-row > .tpl-inline-edit{flex:1 1 auto;width:auto;min-width:0;max-width:100%;box-sizing:border-box;}
/* .qt-opt-row > .qt-correct-label DELETED here (P6c, 2026-09-18) — see the note
   beside .qt-correct-label's own (deleted) rule above. */
/* The correct-answer caption and + ADD OPTION are the option list's own text, so
   they take V5 too — the same token, from the one place it is declared. */
.qt-answer-hint{margin-left:var(--col-nest-x);}
.tpl-add-item[data-add-option]{margin-left:var(--col-nest-x);}
/* Quiet "N items = X comparisons" hint under the pairwise add-item row —
   muted label text, left-aligned to the add button; no badge/warning colour. */
.qt-compare-count{font-family:var(--font-mono);font-size:var(--type-note);line-height:var(--type-note-line);color:var(--color-label);margin-top:var(--gap-tight);padding-top:var(--gap-tight);border-top:1px solid var(--color-border);border-radius:var(--radius-none);text-align:left;}
/* Shared field width (Patterns B/C/D): min+max together, the low/high box, and
   the word-cloud cap all take ONE width so they line up; fluid to the panel on
   mobile via the token (single lever — overridden in the @media block below).
   THE CONFIG FIELD ABSORBS THE BADGE'S LANE (2026-08-20). It was a flat 240px,
   sized for a text lane that has since lost 44px to the reserved badge lane —
   and the rating scale's own low-label placeholder ("e.g. Strongly disagree",
   211px) stopped fitting in what was left, by 25px. The width grows by exactly
   the lane, from the SAME expression the lane is reserved with, so every config
   field's TEXT lane is what it was before the badge got its own: derived, so it
   follows both badge tokens, and not a re-measured literal. */
.qt-subcard{--qcfg-field:calc(240px + var(--tpl-badge-inset) + var(--tpl-badge-size) + 6px);}
/* Pattern C — low/high labelled box: keep the .tpl-section-prompt-input box
   chrome (border/radius/bg/padding) but take the shared field width, overriding
   the Comparison-Question 40% desktop width it used to inherit. */
.qcfg-text{width:var(--qcfg-field);max-width:100%;box-sizing:border-box;}
/* Patterns B/D — canonical config NUMBER box: borderless, digits right-aligned
   with inner padding, height matching the low/high box (same 7px 10px box + the
   same .tpl-abel per width). .criterion-weight-input is config-only.
   ── .qcfg-num — A CONFIG NUMBER FIELD, NOT A WEIGHT STEPPER ─────────────
   These fields used .criterion-weight-input, which is the DM weighting
   stepper's class, and inherited two things from it that are wrong here: a
   RIGHT text alignment (a stepper's digits sit against its arrows; a config
   value belongs under the eyebrow that names it) and the stepper's own box
   padding. The sharing was convenience, not kinship — nothing about "min",
   "max", "max words" or "budget total" is a weight. The stepper is untouched.
  
   Nothing is restated: the field is chrome-less from .tpl-crit-part's own
   declaration like every other field in a part, and left-aligned because that
   is the default it stopped overriding. This rule exists only to say the
   width, which is the one thing a number field genuinely differs on. */
.qcfg-num{box-sizing:border-box;}
/* Pattern B — min/max value row: two equal columns summing to one --qcfg-field,
   so min+max together = one low/high box.
   .qt-pair-row / .qt-pair-cell — the component's own base layout, for the
   surfaces that are NOT the setup page (slim). The setup page states its own
   version against .tpl-crit-part; see start.blade.php. (.qt-numrow is deleted:
   nothing emits it since the bounds pair became a real field row.) */
.qt-pair-row{display:flex;gap:var(--inset-control);}
.qt-pair-cell{flex:1 1 0;min-width:0;}
.qt-pair-cell .qcfg-num{width:100%;}
/* Pattern D — word-cloud cap: one config number box at the shared field width. */
.qt-cap-input{width:var(--qcfg-field);max-width:100%;}
/* Pattern E — pairwise image sub-row: aligned under the option input (numeral +
   row gap), never wider than the panel. */
.qcfg-img-row{margin-left:calc(2rem + var(--col-gap));max-width:100%;flex-wrap:wrap;}
.qt-subcard-toggle{display:flex;align-items:center;gap:var(--inset-control);margin-top:var(--inset-box);cursor:pointer;}
/* Pin the checkbox to an exact 13px square with margin:0 so its box IS its
   visible square (no asymmetric UA margin, no intrinsic-size drift). 13px is the
   tallest child, so the flex row is 13px and the 9px label centres at a whole
   2px offset — alignment comes from normalised boxes, not align-items alone. */
.qt-subcard-toggle input[type="checkbox"]{accent-color:auto;cursor:pointer;margin:0;flex:0 0 auto;width:13px;height:13px;}
/* Toggle labels that opt into .tpl-mono (checklist "Include Don't Know",
   Word-Cloud Free/Select, Weighting Percentage/Budget) read DM Mono 12px
   ink from .tpl-mono; uppercase is scoped to this .qt-subcard-toggle.tpl-mono
   intersection so it never leaks onto .tpl-mono globally (and the Hint
   toggle, whose text is .qt-field-label not .tpl-mono, is unaffected). */
.qt-subcard-toggle.tpl-mono{text-transform:uppercase;}
/* Per-question INSTRUCTION / HINT field (universal, sits OUTSIDE the
   sub-card, under the prompt row and left-aligned to the row edge).
   (The `.qt-guidance .qt-subcard-toggle{margin-top:0;gap:5px}` and
    `.qt-guidance .qt-field-label{margin:0}` rules that used to sit here are
    DELETED with the reveal checkbox they styled. Only the GUIDANCE USE goes:
    .qt-subcard-toggle itself keeps every other consumer — checklist's
    "Don't know" column, the section end-comments toggles, the weighting
    enable — and its shared rules above are untouched.)
   Inside the card the hint starts on the card's own inset, like everything else
   on it — the --qt-prompt-inset offset it used to carry was for the inline
   layout, where the hint sat under a row whose prompt began one rail-width in. */
.qt-guidance{margin-top:0;}
/* text-transform:uppercase mirrors the participant render (.q-guidance,
   blocks.css) so the facilitator sees what participants will — DISPLAY
   ONLY; q.guidance stores the raw value (text-transform never touches it),
   so casing is not mutated.
   Width basis = width:100% of the .qt-guidance block (right edge fills to
   the content-column edge, matching the .qt-subcard below).
   resize:vertical + line-height:1.5 are the SECTION DESCRIPTION textarea's
   own two declarations (templates.css `.tpl-crit-pair .tpl-crit-part
   textarea`), taken because this field is now that field's shape — the height
   comes from rows=2, so no min-height on top of it or the box grows twice. */
.qt-guidance-input{display:block;width:100%;margin-top:var(--inset-control);padding:7px 10px;box-sizing:border-box;text-transform:var(--tpl-config-case);resize:vertical;line-height:var(--type-line-prose);}
/* Options list fills the sub-card (overrides the 80%-width MS rule
   scoped to .tpl-start so the option inputs + × reach the sub-card
   right edge, matching the left inset). Equal specificity, injected
   later → wins. */
.qt-subcard .tpl-items-list.tpl-questions-list{width:100%;}
/* Top-level survey question ROWS: the same 80%-width MS rule
   (.tpl-section-block .tpl-items-list) also catches the per-section
   questions-list — it was meant for the item-entry lists, not the
   question rows — squeezing the prompt input against the fixed 240px
   SELECT TYPE column. Override it to full width so the question input
   expands and the type selector is pushed right; the sub-card below
   widens with the row (intentional). Scoped to the top-level list via
   its data-section-questions-list hook so the sub-card rule above is
   untouched. Injected after the Blade <style> → wins. */
.tpl-start .tpl-section-block .tpl-questions-list[data-section-questions-list]{width:100%;}
/* Per-question collapse/expand chevron (▾ expanded / ▸ collapsed).
   Collapsed hides this row's type-config sub-card; the question
   prompt row stays visible. Default: expanded.
   Collapse chevron reuses the canonical .tpl-card-collapse (the criterion
   card chevron) directly — same 30px bordered box, glyphs, and collapse
   semantics — so there is ONE collapse-button class platform-wide. No
   .qt-row-collapse rule here anymore.
   Per-row duplicate button — ink (matches the × / collapse in the cluster). */
.qt-row-dup{background:none;border:none;cursor:pointer;color:var(--color-text-primary);font-size:var(--type-field);line-height:var(--type-field-line);align-self:center;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;}
.qt-row-dup[disabled]{opacity:0.5;cursor:default;}
/* Shared caption for the per-row QUESTION / SELECT TYPE labels and the
   hint field — one small-caps DM Mono treatment (the same family
   .qt-col-label / .qt-subcard-label were, before they were deleted as dead)
   so every editor caption matches.
   ── .qt-field-label IS THE PAGE'S EYEBROW, NOT A SECOND CAPTION TIER ────
   (DELETED HERE: `display:block;font-family:var(--font-mono);font-size:
    var(--tpl-field-label);letter-spacing:0.14em;text-transform:uppercase;
    color:var(--ink);margin-bottom:4px`.)
  
   It named a field, sat above it, and was ink DM Mono at 12px — while every
   other label that names a field on this surface (.tpl-crit-tag: the MS
   section description, the comparison question, DM's criterion parts, the two
   identity fields) is rust Bebas at --tpl-kicker-size. One role, two answers,
   and the config panel's was the odd one. The class now JOINS the shared
   declaration in templates.css, so the tier lives in exactly one place.
  
   THE CHECKBOX CAPTION IS A DIFFERENT ROLE and keeps its own rule below: it
   sits BESIDE a control rather than above a field, so it is not an eyebrow and
   painting it rust would say something untrue about what it labels. */
.qt-subcard-toggle > .qt-field-label{font-family:var(--font-mono);font-size:var(--tpl-field-label);letter-spacing:0.14em;text-transform:uppercase;color:var(--color-text-primary);margin-bottom:0;}
/* (The old .qt-q-row .qt-field-label{font-size:12px} override is gone — the
   base label is 12px everywhere now, so the per-row bump is redundant.)
   SELECT TYPE / hint captions use the muted base .qt-field-label
   treatment above (DM Mono small-caps) — matching the section-label
   headings. The old prominent (bold/black) column-caption override was
   removed, and the per-row QUESTION caption is now a single
   "Add Questions" heading above the list instead.
   Per-row label layout: the prompt input and the type selector each
   ride in a column with their caption stacked above. The row stretches
   its columns to equal height (the input column is the tallest and
   sets it); the type column then matches, and its tag grows to fill —
   so the selector ends up exactly the input's height (same baseline,
   same top) and the two captions land on one shared label line above
   their controls. Number badge + control buttons opt out of the
   stretch and sit at the bottom, lined up with the inputs. Injected
   after the Blade <style>, so these win the ties against
   .tpl-item-row / .qt-tag-wrap (same specificity). margin-bottom trims the
   8px .tpl-item-row default (line 569) that .tpl-questions-list rows keep
   (the :not(.tpl-questions-list) reset skips them) — that 8px, not the
   guidance margin-top, was the gap above the HINT row. */
.qt-q-row{align-items:stretch;margin-bottom:var(--nudge);flex-wrap:wrap;column-gap:var(--col-gap);}
/* Leading controls (number, drag handle) + the trailing .tpl-row-controls
   cluster (× / ⧉ / collapse) opt out of the row's stretch and bottom-align
   with the inputs. */
.qt-q-row > .tpl-item-num,
.qt-q-row > .tpl-question-drag-handle,
.qt-q-row > .tpl-row-controls{align-self:flex-end;}
.qt-input-col{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;}
.qt-input-col > .tpl-inline-edit{flex:0 0 auto;width:var(--col-line-width);min-width:var(--col-line-width);max-width:100%;box-sizing:border-box;}
/* criteriaMode (DM): prompt inline-edit + duplicate/× share one line, controls
   trailing the [Edit] cue (aligned to the underline via flex-end). */
.qt-crit-line{display:flex;align-items:flex-end;gap:var(--gap-tight);}
/* The type control sizes to its own label now that it is a line of text on the
   card's top line rather than a boxed dropdown filling a reserved column.
  
   (DELETED with the inline layout: `.qt-type-col{flex:0 0 190px;width:190px}` —
   a fixed column "wide enough for the longest label so nothing reflows when the
   type changes" — plus `.qt-type-col > .qt-tag-wrap{flex:1 1 auto;align-self:
   stretch}` and `.qt-type-col .qt-tag{width:100%;justify-content:space-between}`,
   which stretched the control to fill that column and pushed the caret to its far
   edge. All three describe a box that no longer exists; MS already had to
   neutralise them one by one from start.blade.php, and that override goes too.) */
.qt-type-col{flex:0 0 auto;min-width:0;display:flex;flex-direction:column;}
/* THE WRAP-LEVEL NUMERAL IS A BADGE NOW, AND ITS TWO ARMS ARE DELETED FROM
   HERE. `.tpl-start [data-question-wrap] > .tpl-item-num{font-size:22px;
   color:var(--red)}` (and its --active twin) drew rust text on the card's sand.
   A question is a member of a list, and every other member of a list on this
   surface — an MS item, a DM item, a criterion — wears the rust DISC with a
   white glyph. The badge comes from start.blade.php's own two badge
   declarations, which the question ordinal now joins; leaving these here would
   have out-specified the colour and left a rust letter on a rust disc.
  
   THE .qt-q-row ARMS STAY. They are a DIFFERENT numeral: DM's criterion
   questions render with no card, so their number is a child of the row, and
   .tpl-crit-part--questions has its own rule for it further down. Deleting
   these would take that treatment with it. */
.tpl-start .qt-q-row > .tpl-item-num,
.tpl-start .qt-q-row > .tpl-item-num--active{font-family:var(--font-heading);font-size:var(--type-card-name);color:var(--red);letter-spacing:0;line-height:var(--type-card-name-line);}
[data-question-wrap].qt-row-collapsed [data-q-config]{display:none !important;}
/* Per-question CARD - shared desktop + mobile. [data-question-wrap] already
   wraps the .qt-q-row + the .qt-guidance sibling, so it IS the card frame
   (no new markup, no wrappers). Near-white card (--color-background-secondary)
   lifted off the tan questions panel (--card-bg); border --color-border, 8px
   radius. Applies at ALL widths (the @media below only adds the mobile 3-line
   LAYOUT inside it). Slim excluded (Availability Poll reparents its editor into
   its own cards). The wrap's inline margin-bottom:14px is the gap between
   cards; "+ Add Question" is a sibling OUTSIDE the wrap, so it stays below.
   Covers manage too (manage renders as <main class="tpl-start manage-mode">)
   and section question rows (also [data-question-wrap] inside .tpl-start;
   they get the desktop card but no mobile reflow - no .qt-q-row class).
   Swap to --color-white for a starker white if more contrast is wanted.
   SKIN REMOVED (slice 2 of the well work). The card keeps its BOX — 1px, 12/14
   padding, position:relative from the rule at the top of this block — and loses
   its fill and hairline, so a question reads directly on the tan card like every
   other field on the setup surface. border-color:transparent, NOT border:none:
   this element is width:auto, so dropping the border would pull its contents 1px
   left (measured on the wells: every field moved 312.5 -> 311.5), and here it
   would also change the spacing of any bonded stack built out of these borders.
   BLAST RADIUS IS FLAT-ONLY, WHICH IS NARROWER THAN THIS SELECTOR LOOKS. The
   brief for this slice expected it to repaint MS question sections and the DM
   question part too. It does not, and did not before: both already override this
   element to background:transparent;border:0;padding:0 — MS at
   `:has(#tpl-add-section-btn) .tpl-section-block [data-question-wrap]` in
   start.blade.php, DM at `.tpl-crit-part--questions [data-question-wrap]` in
   templates.css — and each paints its own inner card instead (MS's is .qt-card,
   and it is --color-white, not this tint). Verified by computed style on a
   rendered MS page, not by reading. So what changes here is flat survey, flat
   quiz and non-slim availability; slim was already excluded by :not(.slim-mode).
   THE 12/14 PADDING AND THE TRANSPARENT BORDER GO WITH THE CARD (2026-08-20).
   They were the box the fill used to sit in, kept after the fill was removed so
   that nothing shifted 1px. There is no box now — the wrap is a flex row of
   three columns and every one of them is placed by a --col-* token — so the
   padding is what stops the badge and the fields reaching their columns. */
.tpl-start:not(.slim-mode) [data-question-wrap]{background:transparent;border:0;border-radius:var(--radius-none);padding:0;}
/* ══ THE QUESTION CARD ══════════════════════════════════════════════════════
   Promoted OUT of start.blade.php (2026-08-04). It was written there, scoped to
   `:has(#tpl-add-section-btn) .tpl-section-block .tpl-questions-list`, so the
   element this component creates was styled by the page for one surface only.
   It is the component's own element and its own structure, so it is styled
   here, once, and every caller gets it — which is also what makes it survive
   "+ ADD QUESTION" with no post-insert pass.
  
   ── THE BOX IS THE ROW, NOT THE INNER BLOCK (corrected 2026-08-04) ──────
   7bd91936 put the 1px ink border on .qt-card and mounted the numeral, the
   grip and the ×/⧉/▸ cluster on the WRAP so they sat outside it. The markup
   half of that was right and stays: they are the list's controls for the
   question, and having them as wrap-level siblings is exactly what lets ONE
   border enclose the whole row. Only what the border is attached to is
   reversed — it is on the wrapper now, so the row reads as one object with a
   numeral in its left gutter and its glyphs in the right, rather than as a
   box with two loose satellites. A second box was NOT drawn: .qt-card gives
   its border up in the same edit, so there is exactly one line here.
  
   (e) THE ROW BREATHES ON THE SETUP CARDS' OWN SCALE. --tpl-card-pad is
   .tpl-form-card's vertical pair — 18px desktop, 14px ≤640 — so this is not a
   seventh number, it is THE number, read from where the cards read it. The
   padding is on the WRAP, so the numeral and the ×/⧉/▸ cluster move with the
   fields and the three stay aligned; and the ≤640 drop comes free with the
   token rather than needing a media arm of its own.
   ── THE QUESTION BLOCK IS DM'S CRITERION BLOCK ─────────────────────────
   Everything this block used to say about SKIN is DELETED — .qt-card and its
   border, both white fills, the sub-card's tint and hairline, the chip's line,
   the prompt's own metrics. Not overridden: gone, with the element that carried
   them. The treatment now arrives from the classes renderList emits, which are
   DM's own (.tpl-crit-pair / .tpl-crit-part / .tpl-crit-tag / .tpl-rust-rule /
   .tpl-crit-name-input), so the name tier, the eyebrow tier, the eyebrow-to-
   field gap, both underline weights and colours, the field padding and the
   field-group spacing are read from one declaration each and appear nowhere
   here. Comparison in the commit message: measured, property for property.
  
   WHAT STAYS IS LAYOUT, WHICH IS THE COMPONENT'S. DM composes its criterion out
   of Blade in a card; this composes a question out of createElement in a list.
   The four columns are the SAME contract either way, so what follows reads only
   --col-* tokens and states no size of its own.
  
   align-items:BASELINE, matching .tpl-edit-row--header. The field column is tall
   (name + instruction + the type's parts) and the rail entries belong on the
   NAME's line, not centred against the block. flex-start put them at the top of
   the column, which is a pixel or two off the name's cap height and reads as a
   misalignment on the badge.
   flex-wrap:wrap — THE CARD IS TWO ROWS NOW (2026-08-24). The break is
   ARITHMETIC, not luck, and it holds at every width because the wrap's content
   box CAPS at 916px (measured at 1600/1920/2560; the centre column stops
   growing). Row 1 costs handle+badge+chip+cluster = 293.47px at its worst
   (the widest chip label, "Rank Images (Pairwise)", is 164.95px), which leaves
   622.53px; the field row's OUTER size is --col-line-x + --col-line-width =
   74 + 758 = 832px there. 832 > 622.53 by 209px, so it cannot share the line.
   At 390 it is 268 against 32.48 left. Asserted by setup:header-lane, which
   requires the field's top to sit below the chip's bottom on every shape. */
.tpl-start:not(.slim-mode) [data-question-wrap]:has(> .tpl-edit-field){display:flex;flex-wrap:wrap;align-items:baseline;column-gap:var(--col-gap);box-sizing:border-box;}
/* THE QUESTION PROMPT IS CONTENT, NOT A CARD NAME (2026-08-29). It keeps
   .tpl-crit-name-input because the card-name rule it selects also owns the
   ellipsis truncation, which setup:name-truncation asserts by copying that
   rule's three selectors verbatim — so the class stays and only the TYPE is
   taken back. Every value here is the one
   `.tpl-start .tpl-crit-pair .tpl-crit-part input` already gives, i.e. the
   declaration DM's per-criterion question renders through today; this
   subscribes the field to that tier rather than inventing a treatment.
   Scoped through .tpl-crit-part--name, which is where the carded row actually
   mounts the prompt — NOT .qt-input-col, which is the DM / .qt-q-row layout.
   (0,4,1) beats the card-name rule's (0,4,0) on specificity, not on source
   order: this sheet is injected at runtime and must not depend on landing last.
   BASE RULES, DELIBERATELY. The first version of this sat inside the
   `@media(max-width:640px)` block further down and therefore did nothing at any
   width a person was looking at. letter-spacing returns to its initial value;
   there is no token for "none".
   THE TOKENS, NOT A FACE. This arm cannot wear .tpl-field-text — it is a
   .tpl-crit-name-input inside a .tpl-crit-part, so the card-name tier's (0,4,0)
   arm reaches it and a (0,2,0) class would lose. It reads the same --tpl-field-*
   set that class reads, so the field is subscribed to the tier rather than
   holding a second copy of it, which is what the note above already claimed. */
.tpl-start [data-question-wrap] .tpl-crit-part--name > input.tpl-crit-name-input{
font-family:var(--tpl-field-font);font-size:var(--tpl-field-size);
text-transform:var(--tpl-field-case);letter-spacing:var(--tpl-field-tracking);}
/* The field column is column 3 of the contract. Same expression DM's header row
   gives .tpl-edit-field, reached from this component's own structure.
   ── THE FIELD COLUMN, ON A LINE OF ITS OWN ────────────────────────────────
   `flex:0 0 100%` is what puts it there; `max-width:var(--col-line-width)` is
   what keeps the LINE from growing — the basis is clamped down to the column's
   own width, so the rendered box is 438/226 exactly as before and --col-line-max
   is untouched. It was `flex:0 1 auto` + `width:…`, and the SHRINK is what made
   a question row short at <=640: the cluster shared the line and took 40.5px off
   it. Nothing shares the line now, so the shrink term is not merely unused, it
   is wrong to keep.
  
   [HARD] margin-left is --col-line-x, NOT --col-field-lead, and that is not a
   second helping of the lead. A wrapped flex item starts at the CONTAINER's
   content edge, not after the badge, so it has none of the badge column to
   inherit — --col-line-x is the whole distance (--col-num-x + --col-num-left +
   --col-gap + the lead) and CONTAINS the lead exactly once. The base
   .tpl-edit-field rule's `margin-left:var(--col-field-lead)` is REPLACED here,
   not added to; spending both would put V3 at 89 instead of 77 at 390, which is
   the double-spend that already cost this surface a pass on slim's prompt.
  
   The `100%` inside --col-line-width resolves AT THE POINT OF USE, and the point
   of use is this element: its containing block is [data-question-wrap]'s content
   box — 596px at 1280, 302px at 390 — giving 438 and 226. */
.tpl-start:not(.slim-mode) [data-question-wrap] > .tpl-edit-field{flex:0 0 100%;max-width:var(--col-line-width);min-width:0;margin-left:var(--col-line-x);}
/* ── THE TYPE CHIP IS ROW 1's ANCHOR ───────────────────────────────────────
   It is a flex sibling of the badge now, so it is positioned BY FLOW and pays
   --col-field-lead — the difference of the four column terms — to reach V3. Once,
   on this row. The field row above pays its own, inside --col-line-x, on its own
   line; a lead is per-row, and neither row pays the other's. */
.tpl-start:not(.slim-mode) [data-question-wrap] > .qt-type-col{flex:0 0 auto;min-width:max-content;width:auto;align-self:center;margin-left:var(--col-field-lead);}
/* The trailing cluster sits on the name's line rather than on the column's
   baseline, which for a multi-line column is several lines down.
   ── A BADGE ALIGNS TO THE TEXT IT LABELS ────────────────────────────────
   `align-self:flex-start` pinned both of these to the TOP of the field column —
   a column that is name + instruction + the type's own parts — while the name
   sits at the BOTTOM of a row whose height the type chip sets. Measured: the
   question ordinal's centre was 16.00px above the centre of the name it numbers,
   against +0.00 for an item row's badge. See A BADGE ALIGNS TO THE TEXT IT
   LABELS at the badge declarations in start.blade.php for the rule.
  
   margin-top on the name part's own height instead: the rail entries sit on the
   NAME's line, which is the first line of the column, whatever the column does
   below it. Derived from the part's top padding so it follows that token.
   margin-left:auto — the cluster is right-aligned on ROW 1 now, and align-self
   is CENTER rather than baseline: there is no text on this row to share a
   baseline with, only two boxes (a 28px chip and a 30px cluster).
   [HARD] THE CONTROL LANE HAS NOT MOVED, AND margin-left:auto ALONE MOVED IT.
   The lane starts at --col-line-x + --col-line-width + --col-gap — 848.00 at
   1280 — and --col-right is 5.48px wider than the cluster there, so a bare
   auto margin pulled it flush to the card edge at 853.48 and quietly spent the
   headroom CLAUDE.md records as "5.48/0.00". The margin-right gives that
   headroom back, in the same three tokens the lane is defined in. At <=640 the
   expression goes negative (34 - 6 - 68.5), which is the known state where the
   cluster is wider than its reserve; max() floors it at 0 and the cluster sits
   flush, exactly where it sat before. Asserted by setup:header-lane's lane check. */
.tpl-start:not(.slim-mode) [data-question-wrap] > .tpl-row-controls{align-self:center;margin-left:auto;margin-right:max(0px,calc(var(--col-right) - var(--col-gap) - var(--tpl-qrow-ctrl-w)));}
/* [HARD] THE BADGE ALIGNS TO THE FIRST LINE, AND THE FIRST LINE IS THE NAME
   AGAIN (2026-08-21) — so this is back to
   `calc(9px + (var(--tpl-field-height) - var(--tpl-badge-size)) / 2)` = 13px,
   which centres the 26px badge on the 34px name FIELD.
  
   THE FULL HISTORY, because this value has now moved twice for the same reason
   and will move again if the chip does. 13px was correct while the block's first
   row was the name. On 2026-08-20 the chip took a line of its own ABOVE the name,
   so the first row became a captioned control row — 9px of .tpl-crit-part
   padding-top over a 27px content box — and 13px left the badge 3.00px below the
   label it marked; it was cut to a bare 9px, the part's own padding-top. The chip
   now TRAILS the name on the name's row, there is no control row, and the first
   row is a 34px field again. Measured at 1280 with the bare 9px still in place:
   the badge sat 5.00px above the name's centre, which setup:badge-probe caught
   (tolerance 2.0). Restored: 0.00px.
  
   9px is .tpl-crit-part's own padding-top (the badge starts where the row's
   content starts); the second term centres the badge in the field that follows.
   Both halves are read off tokens rather than measured, so the arithmetic closes
   if either the field height or the badge size changes.
  
   THE TELL, if this is ever wrong again: it is wrong by exactly half the
   difference between the badge and whatever the first row's tallest member is.
   Fix it here, at the badge; never by nudging the text.
   [HARD] THE BADGE NOW LABELS ROW 1, SO IT CENTRES ON ROW 1 (2026-08-24), and
   the derived margin-top is DELETED rather than re-derived. That value centred a
   26px badge on a 34px NAME FIELD sitting beside it; the name field is a line
   below now and the badge's own row is a 28px chip and a 30px cluster. The note
   above predicted this exactly — "it is wrong by exactly half the difference
   between the badge and whatever the first row's tallest member is ... it will
   move again if the chip does" — so the fix is to stop computing an offset
   against a specific neighbour and let the line centre it, which needs no
   arithmetic to stay true when the chip's height changes.
   AND THE HALF-RULE LIFT IS CANCELLED HERE TOO (2026-09-08), same reason,
   same place. `.tpl-card-badge`'s `margin-bottom:var(--tpl-rule-weight)` in
   start.blade.php exists so a centre-aligned badge sits on its FIELD'S TEXT
   rather than on the field's border box, which is --tpl-rule-weight taller
   because the underline is a border-bottom. Its own note calls the declaration
   inert under baseline alignment and corrective under centre alignment — true
   of the two rows that existed when it was written, and row 1 of the question
   card is a third: centre-aligned, and NOTHING on it draws a rule. So the lift
   had nothing to compensate and put the ordinal exactly half a rule above the
   centre of the type tag beside it.
  
   Measured, not reasoned: badge centre 650.36 against the tag's 650.86 at 1440
   (and the same +0.50 at 390), and setting this badge's margin-bottom to 0 in
   the live page took the difference to 0.000. Cancelled at the BADGE and only
   for the card's row-1 ordinal — `.qt-q-row > .tpl-item-num`, DM's and slim's
   numeral, still sits beside an underlined prompt and still needs the lift. */
.tpl-start:not(.slim-mode) [data-question-wrap] > .tpl-item-num{align-self:center;margin-top:0;margin-bottom:0;}
/* ── THE HEADER LINE ────────────────────────────────────────────────────────
   .qt-name-row ITSELF IS DELETED (2026-08-29) — display:flex/align-items/
   column-gap and the > input / > .qt-type-col sizing arms that used to sit
   here. It meant exactly one thing, "a name that carries a trailing chip on
   its own line", and had exactly two consumers: the question card's own name
   part (which stopped carrying the class 2026-08-24 — see THE NAME PART IS A
   FIELD AGAIN, AND ONLY A FIELD, further down this file) and MS's section
   header (which stopped carrying it the same day the type chip left the name
   part for a full-bleed tab strip — see THE SECTION TYPE STRIP in
   start.blade.php). Zero remaining emitters, checked by grep before deleting.
   The chip is --tpl-badge-size tall, so the name row's height stops being a
   number nobody declared. That matters beyond tidiness: the rail's ordinal sits
   beside this row, and while the row was 32px the badge could only be centred on
   it by a margin derived from a height the CSS could not name. With the row at
   badge height the arithmetic closes on the badge's own token. */
.tpl-start .tpl-crit-pair > .qt-type-col > .qt-tag-wrap{align-self:center;}
/* (the chip's height arm is DELETED: a wrapping label needs to grow, and the
    page states its min-height with the wrap rule.)
   ── THE TYPE'S OWN PARTS ───────────────────────────────────────────────────
   The config container is a plain region of the pair; its children are parts
   like any other. The gap is stated ONCE here, on the container, rather than as
   a margin on each field the way the old per-builder `marginBottom:8px` was —
   which is what "no per-element vertical margins" means in practice.
   `> *` and not `> * + *`: the first part needs the same distance from the
   Instruction above it as the second needs from the first. */
.tpl-start .tpl-crit-pair > [data-q-config] > *{margin-top:var(--space-md);}
.tpl-start .tpl-crit-pair > [data-q-config]{margin-top:0 !important;}
/* Bounds are the one shape that is two fields on a line. Both are ordinary
   parts; only the ROW is new, and it states no width — --qcfg-field is the
   config field measure this file already declares.
   ── THE ROW SUPPLIES THE HEIGHT, AND THE FLOOR IS THE BADGE ─────────────
   [HARD] A field shorter than its own badge CLIPS it, top and bottom, and it
   looks broken rather than subtly wrong. Measured before this rule: the number
   fields rendered 21px and the display-text body 24px against a 26px ring —
   5px and 2px of the badge cut off, on five of the seventeen types.
  
   The floor is --tpl-field-height (2026-08-20, was --tpl-badge-size). The badge
   size alone stopped the badge being CLIPPED and did nothing more — it let a
   field be exactly as tall as the thing painted on it, so the pencil sat
   directly on the rule beneath. The field height is what the identity fields
   already are, and a 26px badge centred in it leaves the 4px of clearance those
   fields have always had. Both terms are tokens, so the clearance is a leftover
   rather than a number, and it is the same leftover on every field. On the field, not the part, because the
   badge is painted on the field — and only where the field can be short: a
   textarea grows with content and an item row is already 34px, so this raises
   exactly the ones that were clipping. */
.tpl-start .tpl-crit-part input,.tpl-start .tpl-crit-part textarea{min-height:var(--tpl-field-height);}
/* (THE .tpl-start .qt-numrow LAYOUT RULES ARE DELETED. They stated the LOOK of a
   .tpl-crit-part from inside this component, which is the one thing this file must
   not do — see the boundary note on the card below. The pair row they described is
   .qt-pair-row now and the page declares it, once, in start.blade.php.)
   Question-row 3-line layout at ALL WIDTHS (promoted from the former <=640
   reflow, 8e53cc95 + its follow-ups). The number is lifted out of flow into a
   left gutter so .qt-input-col owns line 1 and forces the wrap - a normal flex
   item can't break the line without stranding the number. Line 2 = the type
   dropdown (order:1) + the x/dup/collapse controls (order:2); line 3 = the
   Instructions FOOTER (full-width edge-to-edge via negative margins cancelling
   the card's 14px padding, hairline top border, label inset by padding-left).
   The drag handle is hidden (matches mobile - question reorder was
   mobile-less; this removes it on desktop too), and the number sits flush to
   the card edge (left:-14px lands ~1px inside the 14px card padding; top:6px
   drops the Bebas-22px baseline onto the input's). ONE unconditional layout -
   no width-dependent structure. No-op for DM (no .qt-type-col / no trailing
   controls -> single-line card) and slim.
   Numeral is an IN-FLOW col-2 cell (was position:absolute;left:-14px, whose
   origin drifted across the nested question wrappers). margin-left reserves the
   empty drag gutter; the column-gap after it lands the prompt on --col-line-x by
   construction — same as every item row, no absolute offset to mismeasure. */
.qt-q-row:has(> .tpl-item-num){padding-left:0;}
/* Both parents, for the reason given at the drag-handle rules below: in the
   stacked/card layout the numeral is a rail entry mounted on the wrap, not on
   the row, and the COLUMN it occupies is the same one either way. Enumerated,
   never a descendant selector — .tpl-item-num also names option-row numerals. */
.qt-q-row > .tpl-item-num,
[data-question-wrap] > .tpl-item-num{position:static;flex:0 0 var(--col-num-left);width:var(--col-num-left);margin-left:var(--col-num-x);text-align:left;}
/* Survey question reorder (DESKTOP). The handle is laid out INSIDE the reserved
   gutter, not in front of it: it is --col-drag wide and gives back its whole
   advance (its own width plus the row's column-gap, which is --col-num-x) with a
   negative margin-right, so its net contribution to the row is ZERO and the
   numeral after it lands on the column from its own unconditional --col-num-x.
   Hidden again in the mobile @media below; the Sortable stays initialised but is
   inert with no visible handle, exactly mirroring the section-card reorder gate.
  
   [HARD] THIS REPLACES A TWO-ARM GUTTER (2026-08-24). It used to read
   `margin-right:0` and the numeral DROPPED its margin when a handle was present
   — two arms that summed to the same 26px from the same two tokens, and the
   agreement was the thing that had to hold. It did not always: `width:auto` once
   substituted the braille grip's 11.72px content width for --col-drag and the
   handle arm landed 4.28px short, moving the whole question column the moment a
   section had a second question (see start.blade.php's note). One arm cannot
   disagree with itself. Do not reintroduce a second one. */
.qt-q-row > .tpl-question-drag-handle,
[data-question-wrap] > .tpl-question-drag-handle{width:var(--col-drag);margin-right:calc(-1 * var(--col-num-x));}
/* (DELETED 2026-08-24: `.qt-q-row:has(> .tpl-question-drag-handle) > .tpl-item-num,
    [data-question-wrap]:has(> .tpl-question-drag-handle) > .tpl-item-num
    {margin-left:0}` — the numeral dropping its gutter margin when a handle was
    there to occupy the gutter. It is the second arm of the two-arm gutter and it
    goes with the first: the handle now cancels its own advance, so the numeral's
    --col-num-x is correct in BOTH states and there is nothing left to switch on.
    Its own history is the argument for removing it rather than narrowing it
    again — it shipped as a DESCENDANT :has(), fired for a handle mounted anywhere
    in the wrap, and put the stacked rail one --col-num-x left of the section
    letter and every item numeral; that was narrowed to `:has(> …)` on 2026-08-02
    rather than questioned. A selector that has to ask whether a handle is present
    is the defect, not the answer to it. `:has()` also matches a display:none
    element, so it could never express "occupied" in the first place.
    Enumeration, not a descendant selector, is still the rule for the numeral
    itself — .tpl-item-num also names the numerals inside a type's option rows.)
   input-col fills the rest of line 1 (basis = 100% − the numeral column) so the
   type dropdown + ×/⧉ controls wrap to line 2; the underline inside it is the
   fixed --col-line-width. */
.qt-q-row > .qt-input-col{flex:1 1 calc(100% - var(--col-line-x));}
/* Rows WITH a type dropdown (flat Survey / MS questions): reserve the right-glyph
   gutter (--col-right) on line 1 so the ×/⧉/▸ controls sit beside [Edit] at the end
   of the prompt line, and the dropdown wraps alone to line 2. DM criteria rows have
   no .qt-type-col so they keep the full-width prompt (controls live inline). */
.qt-q-row:has(> .qt-type-col) > .qt-input-col{flex:1 1 calc(100% - var(--col-line-x) - var(--col-right));}
/* (DELETED 2026-09-08: `.qt-q-row .qt-tag{height:auto}`. It cancelled the
    component's own `.qt-tag{height:100%}`, which the split-tag rebuild removed
    at source — the tag is content-height now and its two halves stretch to each
    other via align-items:stretch. A canceller for a declaration that is gone
    reads as though the tag still fights its row for its height.)
   (DELETED: `.qt-q-row > .qt-type-col{order:2;flex:0 0 auto;align-self:flex-end;
    margin-left:var(--col-line-x)}` and `.qt-q-row > .tpl-row-controls{order:1}` —
    the wrap-to-line-2 choreography for the boxed dropdown, and the reorder that
    put the ×/⧉/▸ cluster ahead of it. The chip is the card's top line and the
    cluster is outside the card; neither element is where those rules reach.
    ALSO DELETED: the .qt-guidance FOOTER — `margin:10px -14px 0` with a
    `border-top:1px solid var(--color-border)`. That border IS the divider above
    INSTRUCTION / HINT, and the negative margins were what pushed the footer
    edge-to-edge across the wrap's padding to carry it. Both go with the caption.)
   Dropdown WIDTH is the only width-dependent bit (not layout/structure): desktop
   keeps the fixed .qt-type-col column (190px, base rule above - no type-change
   reflow, no empty stretch across a wide question card); <=640 the dropdown fills
   its own line 2 (the original mobile proportion, so mobile is pixel-unchanged).
   ([Edit] cue is hidden on ALL mobile surfaces via templates.css @media(max-width:
   640px){.tpl-edit-cue{display:none}} - kept there so it also covers blade fields.) */
@media(max-width:640px){
/* (THE CHIP-WRAPS-ONTO-ITS-OWN-LINE PAIR THAT USED TO SIT HERE — `.qt-name-row
   {flex-wrap:wrap;row-gap:...}` and `.qt-name-row > .qt-type-col{flex:0 0 100%}`
   — is DELETED WITH .qt-name-row ITSELF: see THE HEADER LINE above. Nothing at
   <=640 wraps a chip inside a name part any more; the question card's chip is
   its own row-1 anchor and MS's is a full-bleed strip above the header
   entirely, so there is no name-part-plus-trailing-chip shape left on any
   shape for this to apply to.)
   MOBILE ONLY: no drag-reorder — hide the question handle (the --col-drag
   gutter is already 0 on mobile, so numerals sit flush and nothing shifts).
   Mirrors the section-card handle's mobile hide; the Sortable is left
   initialised but has no grabbable handle, so there's no dead affordance. */
.qt-q-row > .tpl-question-drag-handle,
[data-question-wrap] > .tpl-question-drag-handle{display:none;}
/* MOBILE ONLY: move the ×/⧉/▸ controls OFF the prompt line, down onto the
   dropdown line, sitting AFTER the type dropdown — so line 1 (the prompt
   underline) gets the full card width. Desktop keeps the controls beside
   [Edit] on the prompt line (the base rules above, outside this media query,
   are untouched). input-col fills line 1 with NO --col-right reservation, and
   its underline fills input-col (width:100%) — the fixed-px desktop
   --col-line-width didn't nest, but the mobile %-based token double-subtracts
   the gutters against the input-col box, so pin it to 100% here instead. */
.qt-q-row:has(> .qt-type-col) > .qt-input-col{flex:1 1 calc(100% - var(--col-line-x));}
.qt-input-col > .tpl-inline-edit{width:100%;min-width:0;}
/* (The two mobile line-2 ordering rules that sat here — the dropdown at order:1
    and the ×/⧉/▸ cluster at order:2 — went with their desktop counterparts: on
    the card there is no line 2 to order, the chip is the top line and the cluster
    is outside the card at every width.)
   MOBILE ONLY: the whole expanded question sub-area renders at ONE font + ONE
   size — DM Mono 12px, matching the "QUESTION N: RESPONSE OPTIONS" caption
   (12px; .qt-subcard-label named it here until P6c deleted it as dead, 2026-09-18
   — the caption survives, this rule's own wildcard selector doesn't care by name).
   This (0,1,0) rule covers the NON-input elements
   (captions, list/column labels, headings) — none of those have a higher-
   specificity competitor. [data-q-config] is the type-config container (options,
   image labels, min/max, low/high, add buttons, caption; also carries .qt-subcard);
   .qt-guidance is the Instructions field. Desktop keeps its per-element sizes. */
[data-q-config],[data-q-config] *,.qt-guidance,.qt-guidance *{font-family:var(--font-mono);font-size:var(--tpl-field-label);}
/* Leave the "+ Add …" buttons as-is: restore the Bebas "+" glyph the unify rule
   above would otherwise shrink to 12px mono. The label itself is already DM Mono
   12px (.tpl-add-btn), so it's unchanged; only the glyph needs protecting. */
[data-q-config] .tpl-add-item-plus{font-family:var(--font-heading);font-size:var(--type-panel-title);}
/* [HARD] AND A FORM CONTROL SITS ON THE iOS FOCUS-ZOOM FLOOR, NOT ON THE CONFIG TIER
   (2026-09-19, the second half of RR-109). tokens.css's floor has THREE arms and they
   are not the same strength: the `input` arm is (0,3,1) — each :not([attr]) is a
   class-level bump — and beats everything here, which is why config INPUTS were always
   16px on a phone. The `select, textarea` arm is (0,0,1) and loses to `.qt-subcard
   select` (0,1,1) and to the rule directly above (0,1,0), so the three
   `select.tpl-mono` controls in the time/date config rendered 12px at 390 and iOS
   zoomed the viewport on focus.
   MEASURED, NOT INFERRED: /templates/availability/start?slim=1 at 390,
   getComputedStyle on select.tpl-timedate-tz and the two .tpl-timedate-calsel — 12px
   each, with `.qt-subcard select` as the winning rule (matched-rule walk, not a
   reading of the cascade).
   IT WENT UNSEEN BECAUSE NOTHING LOOKED: `setup:field-focus`'s census selector was
   `.tpl-start input…, .tpl-start textarea` and did not include `select` at all. It
   does now, which is what makes this line falsifiable.
   Same shape as the fix in setup-sidebar.css: raise the rule that out-specifies, in
   the file that owns it, using the floor's value EXPRESSION rather than a copy of its
   number. Only ≤640; the config tier is untouched above it. */
[data-q-config] select,[data-q-config] textarea,
.qt-subcard select,.qt-subcard textarea,
.qt-guidance select,.qt-guidance textarea{font-size:max(16px, var(--tpl-field-min, 0px));}
/* (b) INPUT FIELDS. The (0,1,0)/(0,1,1) container rules can NEVER beat the global
   .tpl-start input[type="text"]{color:var(--color-text-primary)} (0,2,1) nor the .tpl-abel 18px on
   the option/label inputs. This selector is (0,3,1) — .tpl-start + [data-question-
   wrap] + [data-q-config] + input — which genuinely out-ranks every competitor, so
   typed fields render DM Mono GREY (grey = "what the user types"). Numerals /
   captions / labels stay ink (targeted separately below).
  
   [HARD] THE SIZE IS --tpl-input-size, NOT --tpl-field-label (2026-08-31), AND
   THE DIFFERENCE IS iOS FOCUS-ZOOM. --tpl-field-label is 12px, and a focused
   <16px input zooms the viewport on iOS Safari; tokens.css's own <=640 arm
   raises every input/select/textarea to 16px for exactly that reason, and this
   rule is one of only two places on the surface that reached back under it (the
   other was start.blade.php's <=640 field block, deleted the same day). The
   container arm above still puts the CAPTIONS and labels at 12px — they are not
   focusable and cannot zoom anything — so the "one size for the sub-area"
   intention survives everywhere it can be honoured. Do not put a size below 16
   on a focusable control at <=640. */
.tpl-start [data-question-wrap] [data-q-config] input,
.tpl-start [data-question-wrap] [data-q-config] select,
.tpl-start [data-question-wrap] [data-q-config] textarea,
.tpl-start [data-question-wrap] .qt-guidance input,
.tpl-start [data-question-wrap] .qt-guidance textarea{font-family:var(--tpl-field-font);font-size:var(--tpl-field-size);color:var(--grey);}
/* (b) The empty option/field text is PLACEHOLDER text ("Option 1", "Insert image
   label", …) — governed by the global input::placeholder{color:var(--color-text-primary)} in
   tokens.css (0,0,2), NOT the input's own color, which is why the grey never showed.
   Override the placeholder to grey for config fields at (0,3,2) so it wins outright.
   Session 176: reads --tpl-ph-color, the ONE placeholder colour declared for
   the whole setup surface (FIELD STATES, templates.css). It used to name
   var(--grey) directly — the same computed value the card-name tier reached
   through --color-label, i.e. a third token path to one colour. Do not
   re-declare a value here; this rule exists only because these selectors are
   more specific than the scope-wide one and would otherwise win with a stale
   colour. */
.tpl-start [data-question-wrap] [data-q-config] input::placeholder,
.tpl-start [data-question-wrap] [data-q-config] textarea::placeholder,
.tpl-start [data-question-wrap] .qt-guidance input::placeholder,
.tpl-start [data-question-wrap] .qt-guidance textarea::placeholder{color:var(--tpl-ph-color);}
/* (c) NUMERALS stay ink (the 01/02 option numbers go grey via .tpl-item-num--active,
   0,2,0; this 0,3,0 rule wins) — structure reads black, only typed text is grey.
   (`.tpl-start [data-q-config] .tpl-item-num{color:var(--color-text-primary)}` and its --active
    twin are DELETED. They painted the option numeral ink at <=640 while the
    base rule painted it 25% ink — two greys for a marker that is a rust disc
    with a white letter on it now. Both would have out-specified the badge's
    white on a phone and left the letter invisible.)
   (d) Pull the option sub-card flush to the card content edge so the 01/02 sit near
   the edge and the option line reclaims width. Scoped to .qt-subcard ONLY, and
   trim its side padding so the numerals sit close to the edge. */
.tpl-start [data-question-wrap] .qt-subcard{margin-left:0;padding-left:var(--inset-control);padding-right:var(--inset-control);}
/* (Option-row layout + quiz-CORRECT wrap are now the unconditional .qt-opt-row
   component above — one rule set at every width. The image sub-row row-inset is
   .qcfg-img-row above; its fields still wrap here, and every field stays capped.) */
[data-q-config] .tpl-item-image-fields{flex-wrap:wrap;max-width:100%;}
[data-q-config] input,[data-q-config] select,[data-q-config] textarea{max-width:100%;box-sizing:border-box;}
/* Config field width goes fluid on the phone: the shared token caps min+max, the
   low/high box and the word-cloud cap to the panel (single lever — the component
   rules above read it). Replaces the former per-element mobile sizing/wrap. */
.qt-subcard{--qcfg-field:100%;}
}
