/* BRI-5620, select-then-confirm interaction reversed by BRI-5692 — see that ticket before editing.
 *
 * The question flow: one card, one question, radio-style option tiles + a free-text row in the
 * same list, Skip (left) and Next (right, bottom-right of the card). Originally BRI-5505's
 * three-button surface; BRI-5620 replaced Accept solution and Add notes with MCQ option tiles + an
 * always-visible free-text fallback, tap-to-advance, no confirm step. BRI-5692 reverses tap-to-
 * advance to select-then-confirm (tapping selects, Next submits) and brings the radio indicator
 * back for exactly that reason. Replaces css/spec-refining.css and css/spec-claim.css, which went
 * with the two-pane refining canvas.
 *
 * MOBILE IS P0 (SPEC-BUILDER-CONTRACT.md §3). Single-column by construction — there is one card,
 * so there is no layout to collapse. No bottom-sheet breakpoint any more (BRI-5620 removed the
 * notes panel that needed one) — the free-text slot is a normal inline block on every viewport.
 *
 * WCAG AA in the site's light theme. brief-homepage has no dark theme (there is not a single
 * prefers-color-scheme rule in css/), so there is no dark variant here and inventing one for this
 * single tool would be un-auditable.
 */

/* Page tokens, carried over from css/spec-refining.css. css/colors.css has no semantic wash for
   either family, so these are minted here. Named for what they MEAN, not for the colour: the same
   green says "Brief affirmed this" wherever it appears, so a change of mind is one edit. */
:root {
  /* Affirmative — the work is done, the cap was earned. */
  --specq-affirm-wash: #ECFDF5;
}

/* ===================== [hidden] MUST WIN ===================== */
/* `[hidden] { display: none }` lives in the USER-AGENT origin, so ANY author-origin `display:`
 * declaration beats it outright — specificity never even enters into it. Several elements here are
 * shown/hidden purely through the `.hidden` DOM property (the banner, the notes panel, the
 * solution block) AND carry a `display:` rule for layout. Without this reset, `el.hidden = true` is
 * a silent no-op while the property still dutifully reads `true` and every unit test stays green.
 *
 * 🔴 THE ROOT SELECTOR NAMES THE CONTAINER, NOT `.specq`. The shell toggles
 * `[data-spec-substate="refining"]` (showSubstate) — and `.specq` is a CHILD of it, so a
 * `.specq[hidden]` rule is inert: nothing ever sets `hidden` on `.specq`. css/spec-building.css
 * can write `.sb[hidden]` only because it puts that class ON its container
 * (`root.classList.add('sb')`); this surface renders a wrapper instead, so the root rule has to say
 * the container's own name or it guards nothing.
 *
 * This matters from page load: the refining container is hidden for the whole constitution phase,
 * so a root reset that misses would paint the question card over the board. It happens to work
 * today because the container carries no author `display` — but "works by accident" is what the
 * next `display` rule quietly breaks, and no unit test can see it (the rig has no CSS).
 *
 * No test can catch this: the suites drive a fake DOM with no CSS at all. Verify in a BROWSER. */
[data-spec-substate='refining'][hidden],
.specq [hidden] {
  display: none !important;
}

/* ===================== LAYOUT ===================== */

.specq {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.specq-heading {
  margin: 0;
}

/* The heading the shell focuses on entry (showSubstate → first h2[tabindex="-1"]). It is
   programmatically focusable, so suppress the ring a mouse-driven focus() would draw;
   :focus-visible still shows it for keyboard users. */
.specq-heading:focus {
  outline: none;
}

.specq-heading:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 4px;
}

/* ===================== THE CARD ===================== */

.specq-card {
  position: relative;   /* BRI-5622 — anchors .specq-loading-overlay's absolute cover */
  padding: 1.5rem;
  border: 1px solid var(--color-border);
  border-radius: 12px;
  background: var(--color-surface);
}

/* BRI-5692 — progress is a top-left EYEBROW again, its own line above the title, reversing
   BRI-5647's move into this row (title/description with progress inline via CardAction). Stephan's
   QA + Brief's own shadcn reference both called for eyebrow-above-title; the row below now holds
   only the title+description pair. */
.specq-title-row {
  margin: 0 0 1rem;
}

/* Text-equivalent progress. NEVER a bar and NEVER a percentage (contract §3): there is no
   denominator we can honestly promise, so there is nothing to fill.
 *
 * BRI-5692: a direct child of `.specq-card`, appended BEFORE `.specq-body` (js/spec-questions-
 * skeleton.js) — the exact placement this had pre-BRI-5647. That placement is load-bearing, not
 * cosmetic: it is OUTSIDE `.specq-card[data-working='true'] .specq-body`'s opacity-0.78 dim (see
 * that rule below), so the AA-contrast fix BRI-5647 needed for this element (a source-color
 * override once it lived inside the dimmed subtree) is dead code now and was deleted, not carried
 * forward — this rule's plain `--color-text-muted` is never composited against the dim. */
.specq-progress {
  margin: 0 0 0.5rem;
  color: var(--color-text-muted);
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

/* BRI-5692 — the problem's short title. Bold, the visual anchor of the card; `.specq-problem`
   below is now its subhead, not the whole prose. `hidden` (js/spec-questions.js) when the stored
   question predates the title field — no empty heading line for those. */
.specq-problem-title {
  margin: 0 0 0.25rem;
  color: var(--color-text);
  font-size: 1.15rem;
  font-weight: 700;
  line-height: 1.4;
}

/* BETWEEN QUESTIONS: the card stays VISIBLE and READABLE while Brief works the answer in. Never a
 * blank card — a 10-20s empty box is the single most expensive moment in the flow.
 *
 * 0.78, not the 0.45 this started as: 0.45 composited body prose to 2.89:1 and the muted labels to
 * 1.92:1 against --color-surface, which FAILS WCAG 1.4.3 and fails the feature's own reason for
 * existing (the user is meant to keep reading through the wait). "Inactive UI component" does not
 * exempt it — this is body content the design intends to be read. 0.78 keeps --color-text at
 * ~5.0:1 and --color-text-secondary above 4.5:1.
 *
 * The status line is a REAL ELEMENT (.specq-working-note) OUTSIDE this subtree, deliberately not a
 * ::after inside it — opacity inherits to pseudo-elements, so the message explaining the wait
 * would itself render at the dimmed contrast. */
.specq-card[data-working='true'] .specq-body {
  opacity: 0.78;
  transition: opacity 160ms ease-out;
}

.specq-working-note {
  margin: 0 0 0.75rem;
  color: var(--color-text-secondary);
  font-size: 0.875rem;
  font-style: italic;
}

/* BRI-5622 — the FULL-treatment loading state: mount()'s pre-first-question wait, the
 * post-last-answer wait, and reenter() (see js/spec-questions.js setWorking()'s `full` rule).
 *
 * NO BOX (Kasyap's live review, screenshots — the first cut kept .specq-card's border around the
 * loading content, which read as a second nested box under the heading). Full mode drops the
 * card's own border outright — the visible OUTLINE is gone, so the overlay's spinner + rotating
 * verb line read as sitting directly on the page, the same as the heading above them.
 *
 * 🔴 THE OVERLAY ITSELF STAYS OPAQUE — this is NOT the same as "transparent". Found live
 * (Claude-in-Chrome): an EARLIER cut set `.specq-loading-overlay`'s background to `transparent`
 * to chase the same "no box" note, and that broke the overlay's actual JOB — with no opaque fill,
 * it stopped hiding anything, and the previous question's problem/solution/buttons (still fully
 * built and visible underneath, not cleared until a NEW render) showed straight through behind
 * the spinner. It needs to be opaque AND match the actual backdrop directly behind it.
 *
 * 🔴 THE BACKDROP IS `.lite-card`, NOT THE PAGE (leavens9, PR #233 round 3). This overlay sits
 * inside `.specq-card` (background: transparent in full mode, see the rule below) inside
 * `.lite-card` (css/lite-form.css: `background: var(--color-surface)`, #FEFEFE) — the shared page
 * wrapper every phase of this tool renders inside, not the page itself. An earlier value here
 * matched `--color-background-subtle` (#F5F5F4) reasoning from the PAGE's own background, but the
 * overlay never reaches the page — `.lite-card` paints over it first. #F5F5F4 on a #FEFEFE
 * backdrop is a flat rectangle with a hard, visible edge — the exact box shape this whole block
 * exists to remove, reintroduced by matching the wrong surface. `var(--color-surface)` matches
 * what is actually painted immediately behind this overlay.
 *
 * 🔴 `.specq-card`'s OWN background must ALSO go transparent here, found live: the overlay's
 * `inset:0` only reaches the card's PADDING edge, not its border edge — the 1px border-width
 * strip sits OUTSIDE that, on the card's own background. Making only `border-color` transparent
 * left the card's white `background` peeking through that 1px strip, a faint but visible ring
 * distinguishable from the page's grey. Both together is what actually removes the shape. */
.specq-card[data-working-mode='full'] {
  border-color: transparent;
  background: transparent;
}

/* 🔴 TRIED AND REVERTED, keep this note so it isn't re-attempted the same way: an earlier cut
 * also suppressed `.lite-card` (css/lite-form.css, the shared page wrapper every phase of this
 * tool renders inside) via `.lite-card:has(.specq-card[data-working-mode="full"]) { background:
 * transparent; border: none; box-shadow: none; }` whenever this state was showing. Confirmed live
 * (Claude-in-Chrome) and then explicitly reversed by Kasyap: a completely boxless loading state —
 * bare heading and spinner floating on the page with no surface under them at all — read as
 * broken/empty, the same complaint this ticket exists to fix, just in a different shape. ONE
 * card (the standard `.lite-card` every other phase already has) is correct; the rule above only
 * removes the SECOND, NESTED box `.specq-card` used to draw inside it. */

/* No knowledge of what it covers — it does not hide .specq-progress/.specq-body/.specq-actions by
 * name, it just sits on top of them, so it stays correct however BRI-5620 reshapes the button/
 * option DOM underneath in parallel.
 *
 * 🔴 z-index:1 IS LOAD-BEARING, found live (Claude-in-Chrome), not by inspection: without it, this
 * absolutely-positioned sibling painted BELOW .specq-body despite z-index:auto theoretically
 * stacking positioned content above static in-flow content — .specq-body's own opacity:0.78 (the
 * INLINE dim rule, below) puts it in a stacking context of its own, and in this browser that
 * context painted AFTER an auto-z-index absolute sibling that comes EARLIER in DOM order. An
 * explicit z-index removes the ambiguity outright rather than relying on DOM order plus an opacity
 * side effect to keep winning. */
.specq-loading-overlay {
  position: absolute;
  z-index: 1;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  padding: 1.5rem;
  background: var(--color-surface);
}

.specq-loading-spinner {
  width: 40px;
  height: 40px;
  border: 3px solid var(--color-border);
  border-top-color: var(--color-primary);
  border-radius: 50%;
  animation: hero-spinner 0.8s linear infinite;   /* reuses css/components.css's existing keyframe */
}

@media (prefers-reduced-motion: reduce) {
  /* The rotating TEXT's reduced-motion handling lives in js/spec-rotating-copy.js (static on
   * phrases[0], read once at load) — that does not touch this separate CSS animation on the
   * spinner ring, so it needs its own guard. */
  .specq-loading-spinner {
    animation: none;
  }
}

.specq-loading-text {
  margin: 0;
  color: var(--color-text-secondary);
  font-size: 0.9375rem;
  text-align: center;
}

.specq-problem {
  /* Margin moved to .specq-title-row, which now owns the gap below the title+description row. */
  margin: 0;
  min-width: 0; /* allow wrapping instead of forcing the row wider than the card */
  color: var(--color-text-secondary);
  font-size: 1rem;
  line-height: 1.55;
}

/* A question stored before BRI-5692 (no problemTitle) renders `.specq-problem` alone — read the
   full-strength text color in that case, not the subhead-muted one above, since there is no title
   line for it to sit under. `hidden` on `.specq-problem-title` (js/spec-questions.js) does the
   detection; this rule targets the sibling relationship directly rather than a second JS-set
   class, so the two can never drift on what "has a title" means. */
.specq-title-row:has(.specq-problem-title[hidden]) .specq-problem {
  color: var(--color-text);
  font-size: 1.05rem;
}

/* ===================== BRI-5620 — MCQ OPTIONS, radio state restored by BRI-5692 =============== */
/* Reuses css/lite-form.css's `.lite-competitor-list`/`.lite-competitor-card` box treatment
 * directly (border-radius, spacing, border-color) — same visual language as the intake form's
 * "What are you hoping it does?" tiles.
 *
 * BRI-5620 dropped the toggle square here on the reasoning that tapping was an immediate,
 * irreversible submit — "that affordance implies 'can be unchecked'". BRI-5692 REVERSES that:
 * tapping now only SELECTS (js/spec-questions.js's chooseOption(), a genuine select-then-confirm
 * interaction, nothing submits until Next), so a real radio indicator (`.specq-option-radio`
 * below) is honest again, not misleading — the option CAN be unchecked, by tapping a different
 * tile, right up until Next is pressed. `.specq-options` itself needs no rules of its own beyond
 * `.lite-competitor-list`'s grid — only the overrides below, because the class here sits on a
 * `<button>`, not the `<li>` the intake form puts it on. */

.specq-option-item {
  /* The grid gap on .lite-competitor-list applies to its direct children (these <li>s); the
     button inside needs to fill that cell for the row to read as one clickable card. */
  display: block;
}

.specq-option-btn {
  display: flex;
  align-items: flex-start;
  width: 100%;
  min-height: 44px; /* ≥44px touch target (contract §3) — explicit, not incidental: do not rely
                        on .lite-competitor-card's padding (css/lite-form.css) to clear this. */
  text-align: left;
  cursor: pointer;
  font: inherit;
  color: inherit;
  /* BRI-5647 — box-reduction pass (D-331): a fainter idle-state border than the inherited
     .lite-competitor-card default (var(--color-border)), matching the shadcn Questionnaire Card
     reference's own option rows (a real border, just far lower-contrast). Scoped to this class,
     NOT edited on .lite-competitor-card itself — that base class is shared with the intake form's
     outcome-chip tiles (tools/spec-builder/index.html) and the competitive-teardown tool
     (js/lite-form.js), neither of which this ticket touches. */
  border-color: var(--color-border-subtle);
  transition: border-color 0.15s ease, background 0.15s ease;
}

.specq-option-btn:hover:not(:disabled) {
  border-color: color-mix(in srgb, var(--color-accent) 45%, var(--color-border));
}

.specq-option-btn:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 2px;
}

.specq-option-btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* BRI-5692 — a SELECTED tile reads as visibly checked before Next is ever pressed: a stronger
   border + a faint accent wash, same visual language `.lite-competitor-card[data-selected="true"]`
   already uses elsewhere in this tool for the same "chosen, not yet committed" state.
   `aria-pressed`, not `aria-checked` (leavens9 review, BRI-5692 — see js/spec-questions-options.js's
   buildOptionTile() comment: a toggle button is what is actually built, so it is what is
   announced; `role="radio"`/`aria-checked` claimed group/arrow-key semantics nothing here
   implements). */
.specq-option-btn[aria-pressed='true'] {
  border-color: var(--color-accent);
  background: color-mix(in srgb, var(--color-accent) 6%, var(--color-surface));
}

/* The radio-STYLED circle — visual language only, not an ARIA radio (see the comment on
   `[aria-pressed='true']` above). Deliberately NOT `.lite-competitor-toggle` (css/lite-form.css)
   — that class is a square checkbox glyph, a different visual language, shared with the intake
   form's multi-select tiles; this is its own circle so a single-pick tile reads differently at a
   glance from a multi-select one, independent of which ARIA role backs either. State is read from
   `aria-pressed` on the parent `<button>` (js/spec-questions-options.js's setSelected()) so the
   visual state and the AT-announced state can never drift — one attribute write drives both. */
.specq-option-radio {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  margin-top: 2px;
  border: 2px solid var(--color-border);
  border-radius: 50%;
  background: var(--color-surface);
  transition: border-color 0.15s ease, background 0.15s ease;
}

.specq-option-btn[aria-pressed='true'] .specq-option-radio {
  border-color: var(--color-accent);
  /* The filled dot. A `radial-gradient` inset rather than a second child element — one fewer node
     for a purely decorative fill, and it repaints for free off the same `aria-pressed` selector
     the border color above already keys on. */
  background: radial-gradient(circle, var(--color-accent) 40%, transparent 44%), var(--color-surface);
}

.specq-option-description {
  margin: 0.25rem 0 0;
  color: var(--color-text-secondary);
  font-size: 0.875rem;
  line-height: 1.5;
}

/* BRI-5647 (D-331), KEPT by BRI-5692 — inline trailing text on the recommended option's own line,
   not a separate boxed/columned tag. It marks a DIFFERENT thing than the radio indicator above
   (WHICH option is Brief's suggestion, not which one is currently selected), so it
   stays even though selection now has its own visible marker — this is not the redundant
   duplicate-marker pattern BRI-5647 itself was filed to fix. Lives INSIDE the button, as a sibling
   of the option's <strong> title inside `.lite-competitor-title`
   (js/spec-questions-options.js's buildOptionTile), so it stays part of the button's own
   accessible name. Muted-secondary color, same weight as the surrounding (non-strong) text — reads
   as metadata about the option, not new emphasis stacked on top of the already-bold title
   (ux-structure: secondary-for-support, emphasis-is-scarce, content-vs-chrome). */
.specq-recommended-note {
  color: var(--color-text-secondary);
}

/* ===================== BRI-5620 — THE FREE-TEXT SLOT, moved into the option list by BRI-5692 == */
/* Reuses css/spec-builder.css's `.lite-field textarea` style exactly (rounded border, placeholder,
 * resize: vertical, focus ring) via the shared `.lite-field` class already on this wrapper — no
 * rules duplicated here beyond the label spacing this specific slot needs. ALWAYS present (no
 * open/close panel state): the last row on a `type:'choice'` question, the only input on
 * `type:'open'`.
 *
 * BRI-5692: no `margin-top` any more. `.specq-freetext` now lives inside `.specq-freetext-item`,
 * one more `<li>` in `.specq-options` (`.lite-competitor-list`, css/lite-form.css) — that list's
 * own `gap` already spaces every row uniformly, tiles and free-text row alike ("in the same
 * list", not a separated section below it). A margin here on top of that gap would make the row
 * before free-text visibly wider than the gaps between tiles. */

.specq-freetext label {
  display: block;
  margin-bottom: 0.375rem;
  color: var(--color-text-secondary);
  font-size: 0.8rem;
  font-weight: 700;
}

/* ===================== ACTIONS (Skip, then Next — BRI-5620 / BRI-5647 / BRI-5692) ============= */
/* BRI-5692 — Skip-left, Next-bottom-right, confirmed by TWO independent sources with no conflict
 * between them: Stephan's shadcn-pattern reference, and Brief's own internal `layout.md`
 * (`commit-bottom-right`: the default/confirming button occupies the bottom-right corner;
 * `cancel-beside-default`: Cancel sits immediately left of it). That is the classic paired-button
 * cluster pushed to one edge, NOT the rag-left row this surface used before — REVERSES BRI-5620's
 * explicitly stated rag-left intent for this row, which the AC requires.
 *   - NOT FULL WIDTH. A full-width button here would read as a bar, the exact thing BRI-5503
 *     ruled out for this surface — still true with the row right-aligned instead of left.
 *
 * DOM order is unchanged from BRI-5647's own live-QA fix: Skip first, Next appended AFTER it
 * (js/spec-questions-skeleton.js) — `justify-content: flex-end` puts that same order at the
 * card's right edge instead of its left, so Skip stays immediately left of Next either way. */
.specq-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: center;
  justify-content: flex-end;
  margin-top: 1.5rem;
}

/* `.specq-actions .btn` is (0,2,0), which beats the shared `button.btn` (0,1,1) in
   css/buttons.css — a single-class override here would LOSE and width/padding would silently not
   apply. */
.specq-actions .btn {
  min-height: 44px; /* ≥44px touch target (contract §3) */
  flex: 0 1 auto;   /* never grow to fill the row */
  width: auto;
  padding: 0 1rem;
}

.specq-actions .btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* The notes-panel bottom-sheet/inline-editor rules (BRI-5505/BRI-5527) are gone — BRI-5620 removed
 * the panel entirely. The free-text slot's textarea styling comes from css/spec-builder.css's
 * `.lite-field textarea` (already loaded on this page), reused exactly rather than duplicated. */

/* ===================== BANNER (never a modal) ===================== */

.specq-banner {
  display: flex;
  flex-wrap: wrap;
  gap: 0.625rem;
  align-items: center;
  padding: 0.875rem 1rem;
  border: 1px solid var(--color-border);
  border-radius: 10px;
  background: var(--color-background-subtle);
}

/* 🔴 These two are built by js/spec-turn-engine.js, not by this screen, so they carry the
   engine-neutral `spec-banner-*` names rather than `specq-*` — BRI-5506 mounts the same engine and
   would otherwise get an unstyled banner. The pairing is pinned by tests/spec-seam-guards.test.mjs
   because no unit test can see it: the rig has no CSS, so an unstyled banner is invisible there and
   obvious in a browser. */
.spec-banner-text {
  flex: 1 1 12rem;
  color: var(--color-text-secondary);
  font-size: 0.9rem;
  line-height: 1.5;
}

.spec-banner-btn {
  min-height: 44px;
}

/* THE CAP — the strongest conversion moment in the flow. Earned and positive, never "you're out".
   A warm invitation with the claim right there, not an error. */
.specq-capped {
  width: 100%;
  padding: 1rem;
  border: 1px solid var(--color-accent);
  border-radius: 10px;
  background: var(--specq-affirm-wash);
}

.specq-capped-title {
  margin: 0 0 0.375rem;
  font-weight: 700;
  color: var(--color-accent-dark);
}

.specq-capped-body {
  margin: 0 0 0.75rem;
  color: var(--color-text-secondary);
  line-height: 1.55;
}

.specq-capped .btn {
  min-height: 44px;
}

/* A finalize failure reported INSIDE the capped card, so the message and the only claim CTA
   available in that state survive together — showBanner() would have wiped both. */
.specq-capped-error {
  margin: 0.75rem 0 0;
  color: var(--color-text-secondary);
  font-size: 0.875rem;
  line-height: 1.5;
}

/* The interim ready-state CTA. TEMPORARY — BRI-5506 replaces this whole state with the real
   final-spec document. It exists so the flow never dead-ends before that ticket lands. */
.specq-interim-claim {
  min-height: 48px;
  margin-top: 1.25rem;
}

/* ===================== LIVE REGION ===================== */
/* Visually hidden, but announced. One announcement per question, never per keystroke. */

.specq-live {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* No BRI-5620 desktop override needed: the free-text slot is a normal inline block on every
   viewport (never a bottom sheet), so there is nothing here to swap at the 880px breakpoint. */

/* ===================== REDUCED MOTION ===================== */
/* The contract calls this out by name. Nothing here carries meaning in motion — the dim is a state
   the status line already states in words — so removing it costs nothing. */

@media (prefers-reduced-motion: reduce) {
  .specq-card[data-working='true'] .specq-body {
    transition: none;
  }

  /* The shared .btn carries `transition: all` and .btn-primary a hover translate
     (css/components.css). */
  .specq .btn {
    transition: none;
  }

  .specq .btn-primary:hover {
    transform: none;
  }
}
