/**
 * The control layer. `aieo-table.css`'s sibling.
 *
 * > An admin panel is a huge form. A survey is a form. They should be the same
 * > controls.
 *
 * That sentence is the whole reason this file exists and the reason it landed
 * in the same wave as the table language rather than later. Wave 2 of
 * docs/PLAN-2026-08-30-CUSTOMER-SURVEYS.md needs a questionnaire renderer;
 * docs/PLAN-2026-08-30-METRONIC-TABLE-LANGUAGE.md needs a variant vocabulary;
 * both consume `aieo-tokens.css`, and `definition_version` is a content hash,
 * so a token rename done twice re-exports every definition twice.
 *
 * ── The prefix, and why it is not the one the plan wrote down ────────────────
 *
 * The plan names these `aieo-scale`, `aieo-rating`, `aieo-choice`. Two of those
 * are TAKEN: `aieo-rating` is the storefront's product star rating (14 files)
 * and `aieo-badge` is the admin top bar's version chip, and `--aieo-btn-*` is
 * already the storefront's master add-to-cart token set. A control layer that
 * silently restyles a product rating on a shop page is the same class of defect
 * as shipping a global `.flex` into wp-admin. So every class here is
 * `aieo-c-*` — c for control — which is greppable, collision-free, and says
 * which layer a class belongs to at a glance.
 *
 * ── Two rules that decide the API ────────────────────────────────────────────
 *
 * 1. THE BLUEPRINT DECLARES THE SEMANTIC, NEVER THE WIDGET. A question says
 *    "scale, 1 to 10, these end labels". Whether that draws as a slider, a
 *    segmented row of buttons or eleven radios is a per-SURFACE decision: a 1-5
 *    satisfaction on a phone reads better segmented, a 1-10 NPS reads better as
 *    a slider. Bake the widget into the data and neither can ever be improved.
 *    So `aieo-c-scale` has MODES, and the mode is a class on the wrapper.
 * 2. BEHAVIOUR KEYS ON `aieo-c-*` AND `data-aieo-*` ONLY. Never on a
 *    presentational class. `aieo-table.js` was built this way — 19 selectors,
 *    all structural — and it is why sort, filter, paging and bulk survived a
 *    restyle untouched. `aieo-controls.js` inherits the rule.
 *
 * ── Accessibility is not a polish pass here ──────────────────────────────────
 *
 * This layer renders to CUSTOMERS, not only to operators. Three things are
 * therefore requirements rather than nice-to-haves, and each is enforced by the
 * markup contract below rather than left to the caller:
 *
 *   - every control is keyboard-operable, including the scale and the ranking;
 *   - the ranking has up/down buttons, because drag alone is unusable for a
 *     large minority of shoppers and impossible on some assistive tech;
 *   - every control has a real associated label, and a group of them has a
 *     `<fieldset>` with a `<legend>`, so a screen reader reads the QUESTION
 *     before the answers rather than five unattached words.
 *
 * @since 11.1.7
 */

/* ---------------------------------------------------------------------
 * Buttons
 *
 * 🚨 THIS IS THE PRODUCT'S WORST PORTABILITY GAP, closed. Everything we render
 * today wears WordPress core's `.button`, `.button-primary`, `.button-small`,
 * `.button-link` — core-styled, with no twin anywhere else, so not one of them
 * travels. `aieo-c-btn` is the same set of intents in our own paint.
 *
 * ⏳ Row actions have NOT been switched onto it in this wave. That is deliberate
 * staging, not an omission: it restyles the actions of 247 tables at once, and
 * a visible change that size deserves its own step and its own screenshots.
 * `AIEO_Variants::wp_button_class()` is the single line that flips it.
 *
 * Intent only — no `success`, no `warning`, no `info`. A button is an ACTION,
 * so it carries what pressing it does; a status is what a badge is for. That
 * asymmetry is a design principle we are adopting rather than a gap we are
 * inheriting.
 * ------------------------------------------------------------------ */

.aieo-c-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 6px;
	box-sizing: border-box;
	height: 34px;
	padding: 0 12px;
	border: 1px solid transparent;
	border-radius: var(--aieo-radius-md, 6px);
	font-size: var(--aieo-text-sm, 13px);
	font-weight: 500;
	line-height: 1;
	white-space: nowrap;
	text-decoration: none;
	cursor: pointer;
	box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
	transition: background-color .12s ease, color .12s ease, border-color .12s ease;

	/* The DEFAULT is deliberately not primary. A bare `.kt-btn` paints solid
	 * primary, which is how 48 delete buttons in the Panel rendered blue and
	 * nobody filed it — a blue button looks intentional. An unclassed button
	 * here is a plain one, so a missing variant reads as an oversight rather
	 * than as a decision. */
	background: var(--aieo-secondary, #f4f4f5);
	color: var(--aieo-secondary-fg, #18181b);
}

.aieo-c-btn:hover,
.aieo-c-btn:focus { color: var(--aieo-foreground, #09090b); }

.aieo-c-btn:focus-visible {
	outline: none;
	border-color: var(--aieo-ring, #a1a1aa);
	box-shadow: 0 0 0 3px rgba(161, 161, 170, .3);
}

.aieo-c-btn[disabled],
.aieo-c-btn[aria-disabled="true"] {
	opacity: .5;
	pointer-events: none;
	cursor: not-allowed;
}

.aieo-c-btn--primary {
	background: var(--aieo-primary, #3b82f6);
	color: var(--aieo-primary-fg, #fff);
}
.aieo-c-btn--primary:hover,
.aieo-c-btn--primary:focus { color: var(--aieo-primary-fg, #fff); filter: brightness(.94); }

.aieo-c-btn--secondary {
	background: var(--aieo-secondary, #f4f4f5);
	color: var(--aieo-secondary-fg, #18181b);
}

.aieo-c-btn--destructive {
	background: var(--aieo-destructive, #dc2626);
	color: var(--aieo-destructive-fg, #fff);
}
.aieo-c-btn--destructive:hover,
.aieo-c-btn--destructive:focus { color: var(--aieo-destructive-fg, #fff); filter: brightness(.94); }

.aieo-c-btn--mono {
	background: var(--aieo-mono, #09090b);
	color: var(--aieo-mono-fg, #fff);
}
.aieo-c-btn--mono:hover,
.aieo-c-btn--mono:focus { color: var(--aieo-mono-fg, #fff); }

.aieo-c-btn--outline {
	background: var(--aieo-background, #fff);
	border-color: var(--aieo-input, #e4e4e7);
	color: var(--aieo-secondary-fg, #18181b);
}
.aieo-c-btn--outline:hover { background: var(--aieo-accent, #f4f4f5); }

/* Present, but not competing. `ghost` reacts on hover, `dim` never does — the
 * difference between "a secondary action" and "a control that is here because
 * it has to be somewhere". */
.aieo-c-btn--ghost {
	background: transparent;
	box-shadow: none;
	color: var(--aieo-accent-fg, #18181b);
}
.aieo-c-btn--ghost:hover { background: var(--aieo-accent, #f4f4f5); }

.aieo-c-btn--dim {
	background: transparent;
	box-shadow: none;
	color: var(--aieo-muted-fg, #71717a);
}
.aieo-c-btn--dim:hover { background: transparent; color: var(--aieo-foreground, #09090b); }

/* Sizes. ⚠️ There is no `xs`. The vendor's buttons stop at `sm` and its badges
 * go to `xs`, which is not an oversight — a control you press needs a target,
 * a label you read does not. */
.aieo-c-btn--sm { height: 28px; padding: 0 10px; font-size: var(--aieo-text-xs, 12px); gap: 5px; }
.aieo-c-btn--lg { height: 40px; padding: 0 16px; font-size: var(--aieo-text-base, 14px); }

.aieo-c-btn--block { display: flex; width: 100%; }

/* ---------------------------------------------------------------------
 * Badges. Status, so three variants the buttons do not get.
 * ------------------------------------------------------------------ */

.aieo-c-badge {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 5px;
	height: 24px;
	padding: 0 7px;
	border: 1px solid transparent;
	border-radius: var(--aieo-radius-md, 6px);
	font-size: var(--aieo-text-xs, 12px);
	font-weight: 500;
	line-height: 1;
	white-space: nowrap;
	background: var(--aieo-secondary-soft, #f4f4f5);
	color: var(--aieo-secondary-soft-fg, #3f3f46);
}

.aieo-c-badge--sm { height: 20px; padding: 0 5px; font-size: var(--aieo-text-2xs, 11px); border-radius: var(--aieo-radius-sm, 4px); }

.aieo-c-badge--primary     { background: var(--aieo-primary-soft, #dbeafe);     color: var(--aieo-primary-soft-fg, #1e40af); }
.aieo-c-badge--secondary   { background: var(--aieo-secondary-soft, #f4f4f5);   color: var(--aieo-secondary-soft-fg, #3f3f46); }
.aieo-c-badge--success     { background: var(--aieo-success-soft, #dcfce7);     color: var(--aieo-success-soft-fg, #166534); }
.aieo-c-badge--warning     { background: var(--aieo-warning-soft, #fef9c3);     color: var(--aieo-warning-soft-fg, #854d0e); }
.aieo-c-badge--destructive { background: var(--aieo-destructive-soft, #fee2e2); color: var(--aieo-destructive-soft-fg, #991b1b); }
.aieo-c-badge--info        { background: var(--aieo-info-soft, #ede9fe);        color: var(--aieo-info-soft-fg, #5b21b6); }
.aieo-c-badge--mono        { background: var(--aieo-mono-soft, #f4f4f5);        color: var(--aieo-mono-soft-fg, #18181b); }

/* Ours, and not in the vendor's vocabulary. See AIEO_Variants::BADGE_VARIANTS:
 * a row that is STILL LISTED but no longer live is a state the product really
 * has and `secondary` is the wrong word for it. */
.aieo-c-badge--muted { background: var(--aieo-muted, #f4f4f5); color: var(--aieo-tone-muted, #a1a1aa); }

/* ---------------------------------------------------------------------
 * The field: label, control, help, error.
 *
 * A question is not an input. It is a label, an input, an optional hint and an
 * optional failure message, and the four have to be ASSOCIATED — `for`/`id`,
 * `aria-describedby` — or a screen reader reads them as four unrelated things
 * in a row. This wrapper is what makes that association the default shape
 * rather than something each caller remembers.
 * ------------------------------------------------------------------ */

.aieo-c-field { margin: 0 0 18px; }
.aieo-c-field:last-child { margin-bottom: 0; }

.aieo-c-label {
	display: block;
	margin: 0 0 6px;
	font-size: var(--aieo-text-sm, 13px);
	font-weight: 500;
	color: var(--aieo-foreground, #09090b);
}

/* The required marker is `aria-hidden` in the markup: the asterisk is a visual
 * convention and `required` on the input is what a screen reader announces.
 * Marking it up twice reads as "star required" out loud. */
.aieo-c-req { color: var(--aieo-destructive, #dc2626); margin-left: 2px; }

.aieo-c-help {
	margin: 6px 0 0;
	font-size: var(--aieo-text-xs, 12px);
	color: var(--aieo-muted-fg, #71717a);
}

.aieo-c-error {
	margin: 6px 0 0;
	font-size: var(--aieo-text-xs, 12px);
	color: var(--aieo-destructive, #dc2626);
}

/* A group of related answers is a fieldset, and its legend is the question.
 * The legend is styled to look like a label rather than a browser legend,
 * because the default rendering is a border interruption that nobody wants and
 * everybody removes — usually by using a <div> instead, which is how the
 * grouping gets lost. */
.aieo-c-group { margin: 0 0 18px; padding: 0; border: 0; min-width: 0; }
.aieo-c-group > legend {
	display: block;
	width: 100%;
	margin: 0 0 8px;
	padding: 0;
	font-size: var(--aieo-text-sm, 13px);
	font-weight: 500;
	color: var(--aieo-foreground, #09090b);
}

/* ---------------------------------------------------------------------
 * Text inputs, textareas, selects
 * ------------------------------------------------------------------ */

.aieo-c-input,
.aieo-c-textarea,
.aieo-c-select {
	display: block;
	box-sizing: border-box;
	width: 100%;
	max-width: 100%;
	background: var(--aieo-background, #fff);
	border: 1px solid var(--aieo-input, #e4e4e7);
	border-radius: var(--aieo-radius-md, 6px);
	color: var(--aieo-foreground, #09090b);
	font-size: var(--aieo-text-sm, 13px);
	box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
	transition: border-color .12s ease, box-shadow .12s ease;
}

.aieo-c-input,
.aieo-c-select { height: 34px; padding: 0 12px; line-height: 32px; }
.aieo-c-textarea { min-height: 88px; padding: 8px 12px; line-height: 1.5; resize: vertical; }

.aieo-c-input::placeholder,
.aieo-c-textarea::placeholder { color: var(--aieo-muted-fg, #71717a); }

.aieo-c-input:focus,
.aieo-c-textarea:focus,
.aieo-c-select:focus {
	outline: none;
	border-color: var(--aieo-ring, #a1a1aa);
	box-shadow: 0 0 0 3px rgba(161, 161, 170, .3);
}

/* ⚠️ `aria-invalid`, not a `.is-error` class. The attribute is what assistive
 * tech reads, so styling off it makes the visual state and the announced state
 * the same fact rather than two facts a caller has to remember to set together. */
.aieo-c-input[aria-invalid="true"],
.aieo-c-textarea[aria-invalid="true"],
.aieo-c-select[aria-invalid="true"] { border-color: var(--aieo-destructive, #dc2626); }

.aieo-c-input:disabled,
.aieo-c-textarea:disabled,
.aieo-c-select:disabled { opacity: .6; cursor: not-allowed; }

.aieo-c-input--sm { height: 28px; padding: 0 10px; line-height: 26px; font-size: var(--aieo-text-xs, 12px); }

/* A field that should not stretch to the width of an admin screen. Long
 * answers want room; a postcode does not. */
.aieo-c-field--narrow .aieo-c-input,
.aieo-c-field--narrow .aieo-c-select { max-width: 260px; }

/* ---------------------------------------------------------------------
 * Choice: radios and tick boxes, as rows you can click anywhere on.
 *
 * The whole row is the label, which matters more on a phone than anywhere
 * else: a 16px radio is a 16px target, and a survey answered on a phone with
 * 16px targets is a survey with a completion-rate problem nobody attributes to
 * the control.
 * ------------------------------------------------------------------ */

.aieo-c-choice { display: flex; flex-direction: column; gap: 6px; }
.aieo-c-choice--inline { flex-direction: row; flex-wrap: wrap; gap: 8px 16px; }

.aieo-c-choice-item {
	display: flex;
	align-items: flex-start;
	gap: 8px;
	margin: 0;
	padding: 8px 10px;
	border: 1px solid var(--aieo-border, #ececee);
	border-radius: var(--aieo-radius-md, 6px);
	font-size: var(--aieo-text-sm, 13px);
	line-height: 1.4;
	cursor: pointer;
}

.aieo-c-choice--inline .aieo-c-choice-item { padding: 6px 10px; }

.aieo-c-choice-item:hover { background: var(--aieo-accent, #f4f4f5); }

.aieo-c-choice-item input { margin: 1px 0 0; flex: 0 0 auto; }

/* `:has()` degrades to "no highlight" where it is unsupported, which is a
 * cosmetic loss and not a functional one — the native control still shows its
 * own checked state. That is the right way round for a progressive selector. */
.aieo-c-choice-item:has(input:checked) {
	border-color: var(--aieo-primary, #3b82f6);
	background: var(--aieo-primary-soft, #dbeafe);
}

.aieo-c-choice-item:has(input:focus-visible) {
	box-shadow: 0 0 0 3px rgba(161, 161, 170, .3);
}

.aieo-c-choice-sub {
	display: block;
	margin-top: 2px;
	font-size: var(--aieo-text-xs, 12px);
	color: var(--aieo-muted-fg, #71717a);
}

/* ---------------------------------------------------------------------
 * Scale — ONE semantic, two widgets.
 *
 * `choice/one/scale` in the blueprint's four axes: 1-5 satisfaction, 1-10 NPS,
 * agree/disagree. The blueprint says min, max and the end labels; the SURFACE
 * picks segmented or slider. Both write the same value to the same hidden
 * input, so switching mode later changes no stored data — which is the entire
 * argument for not baking the widget into the question.
 * ------------------------------------------------------------------ */

.aieo-c-scale { display: block; }

.aieo-c-scale-ends {
	display: flex;
	justify-content: space-between;
	gap: 12px;
	margin: 6px 2px 0;
	font-size: var(--aieo-text-xs, 12px);
	color: var(--aieo-muted-fg, #71717a);
}

/* ── Segmented: a row of real radios drawn as buttons.
 *
 * 🚨 THEY ARE REAL RADIOS. The visible button is a <label> and the input is
 * visually hidden but focusable — never `display:none`, which removes it from
 * the tab order and from the accessibility tree. So arrow keys move between
 * options for free, because that is what a radio group already does, and the
 * "keyboard operable" requirement costs nothing rather than being reimplemented
 * badly in JavaScript. */
.aieo-c-scale--segmented .aieo-c-scale-opts {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
}

.aieo-c-scale-opt {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: 1 1 auto;
	min-width: 44px;      /* a real touch target, not a 16px radio */
	min-height: 40px;
	margin: 0;
	padding: 0 10px;
	border: 1px solid var(--aieo-input, #e4e4e7);
	border-radius: var(--aieo-radius-md, 6px);
	background: var(--aieo-background, #fff);
	color: var(--aieo-secondary-fg, #18181b);
	font-size: var(--aieo-text-sm, 13px);
	font-weight: 500;
	line-height: 1.2;
	text-align: center;
	cursor: pointer;
	transition: background-color .12s ease, border-color .12s ease, color .12s ease;
}

.aieo-c-scale-opt:hover { background: var(--aieo-accent, #f4f4f5); }

/* Visually hidden, NOT hidden. The clip-rect idiom rather than
 * `display:none`/`visibility:hidden`, both of which take the input out of the
 * tab order and take the group out of the accessibility tree. */
.aieo-c-scale-opt > input,
.aieo-c-rating-opt > input {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

.aieo-c-scale-opt:has(input:checked) {
	background: var(--aieo-primary, #3b82f6);
	border-color: var(--aieo-primary, #3b82f6);
	color: var(--aieo-primary-fg, #fff);
}

/* The focus ring has to be on the LABEL, because the input it belongs to is
 * one pixel wide and clipped. Without this the keyboard user moves through the
 * group with no visible indication of where they are. */
.aieo-c-scale-opt:has(input:focus-visible),
.aieo-c-rating-opt:has(input:focus-visible) {
	outline: 2px solid var(--aieo-ring, #a1a1aa);
	outline-offset: 2px;
}

/* ── Slider: a native range, with the current value read out beside it.
 *
 * ⚠️ A slider with no visible value is a control that cannot be answered
 * accurately — the user knows they moved it, not what they moved it to. The
 * read-out is `aria-live="polite"` so it is announced as well as shown. */
.aieo-c-scale--slider .aieo-c-scale-row {
	display: flex;
	align-items: center;
	gap: 12px;
}

.aieo-c-scale-range {
	flex: 1 1 auto;
	width: 100%;
	min-width: 0;
	accent-color: var(--aieo-primary, #3b82f6);
	height: 22px;
}

.aieo-c-scale-out {
	flex: 0 0 auto;
	min-width: 34px;
	height: 28px;
	padding: 0 8px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	border-radius: var(--aieo-radius-md, 6px);
	background: var(--aieo-primary-soft, #dbeafe);
	color: var(--aieo-primary-soft-fg, #1e40af);
	font-size: var(--aieo-text-sm, 13px);
	font-weight: 600;
	font-variant-numeric: tabular-nums;
}

/* Not answered yet is a THIRD state, and it is not zero. Our own ingest writes
 * a literal 0 for a skipped NPS and the report has to exclude it; a slider that
 * starts at its own minimum manufactures the same problem at the source, by
 * recording an answer from someone who never touched the control. */
.aieo-c-scale-out[data-aieo-empty="1"] {
	background: var(--aieo-muted, #f4f4f5);
	color: var(--aieo-muted-fg, #71717a);
	font-weight: 400;
}

/* ---------------------------------------------------------------------
 * Rating — stars, on the same real-radio mechanism as the segmented scale.
 *
 * ⚠️ A star is a scale with a picture on it, which is why it shares the
 * markup. What it must NOT share is the assumption that more is better: the
 * caller declares the labels, so a five-star "how difficult was this" reads
 * correctly instead of being silently inverted by the icon.
 * ------------------------------------------------------------------ */

.aieo-c-rating { display: inline-flex; align-items: center; gap: 2px; direction: ltr; }

.aieo-c-rating-opt {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 34px;
	height: 34px;
	margin: 0;
	cursor: pointer;
	color: var(--aieo-input, #e4e4e7);
	font-size: 22px;
	line-height: 1;
	border-radius: var(--aieo-radius-sm, 4px);
}

/* The fill runs from the left up to and including the hovered/checked star,
 * which is what a rating means and what a per-star `:checked` rule cannot say.
 * `:has()` plus a sibling combinator gets there with no JavaScript: colour
 * every star, then un-colour the ones AFTER the checked one. */
.aieo-c-rating-opt { color: var(--aieo-warning, #facc15); }
.aieo-c-rating:has(input:checked) .aieo-c-rating-opt { color: var(--aieo-warning, #facc15); }
.aieo-c-rating-opt:has(input:checked) ~ .aieo-c-rating-opt { color: var(--aieo-input, #e4e4e7); }

/* Nothing chosen: every star is empty. Without this the group would render
 * fully lit before it has been answered, which is the same manufactured-answer
 * defect as a slider parked on its minimum. */
.aieo-c-rating:not(:has(input:checked)) .aieo-c-rating-opt { color: var(--aieo-input, #e4e4e7); }

.aieo-c-rating-opt:hover { background: var(--aieo-accent, #f4f4f5); }

/* ---------------------------------------------------------------------
 * Rank — drag to order, and ALWAYS operable without dragging.
 *
 * 🚨 THE UP/DOWN BUTTONS ARE NOT A FALLBACK, THEY ARE THE CONTROL. Drag is the
 * enhancement. Pointer dragging is unavailable or unreliable for a large
 * minority of shoppers — motor impairment, a trackpad, a touch screen inside a
 * scrolling page, any screen reader — and a ranking question that only accepts
 * a drag is a question that silently excludes them and reads afterwards as a
 * low response rate on that question alone.
 *
 * The stored value is a hidden input holding the codes in order, rewritten on
 * every move, so the answer survives with JavaScript half-loaded and the server
 * never has to reconstruct an order from DOM position.
 * ------------------------------------------------------------------ */

.aieo-c-rank { display: flex; flex-direction: column; gap: 6px; margin: 0; padding: 0; list-style: none; }

.aieo-c-rank-item {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 8px 10px;
	background: var(--aieo-background, #fff);
	border: 1px solid var(--aieo-border, #ececee);
	border-radius: var(--aieo-radius-md, 6px);
	font-size: var(--aieo-text-sm, 13px);
}

.aieo-c-rank-item[draggable="true"] { cursor: grab; }
.aieo-c-rank-item.is-dragging { opacity: .5; }

/* The drop target line. Drawn on the item being hovered over rather than as a
 * separate element, so there is no layout shift while dragging — a list that
 * reflows under the pointer makes the drop land somewhere the user did not
 * aim. */
.aieo-c-rank-item.is-over { border-color: var(--aieo-primary, #3b82f6); box-shadow: inset 0 2px 0 var(--aieo-primary, #3b82f6); }

.aieo-c-rank-pos {
	flex: 0 0 auto;
	min-width: 22px;
	height: 22px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	border-radius: var(--aieo-radius-pill, 999px);
	background: var(--aieo-muted, #f4f4f5);
	color: var(--aieo-muted-fg, #71717a);
	font-size: var(--aieo-text-2xs, 11px);
	font-weight: 600;
	font-variant-numeric: tabular-nums;
}

.aieo-c-rank-label { flex: 1 1 auto; min-width: 0; }

.aieo-c-rank-moves { flex: 0 0 auto; display: inline-flex; gap: 4px; }

.aieo-c-rank-move {
	width: 26px;
	height: 26px;
	padding: 0;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	border: 1px solid var(--aieo-input, #e4e4e7);
	border-radius: var(--aieo-radius-sm, 4px);
	background: var(--aieo-background, #fff);
	color: var(--aieo-secondary-fg, #18181b);
	font-size: 11px;
	line-height: 1;
	cursor: pointer;
}
.aieo-c-rank-move:hover { background: var(--aieo-accent, #f4f4f5); }
.aieo-c-rank-move[disabled] { opacity: .4; cursor: not-allowed; }

.aieo-c-rank-grip {
	flex: 0 0 auto;
	color: var(--aieo-muted-fg, #71717a);
	cursor: grab;
	user-select: none;
	line-height: 1;
}

/* ---------------------------------------------------------------------
 * Steps — where you are in a multi-page questionnaire.
 *
 * The 2023 forms put 69 and 83 fields on ONE page with no progress and no
 * resume, which is the single most likely reason a long survey is abandoned
 * three questions in. This is the control that fixes it, and it is worth
 * nothing unless it is honest: it shows the real count, never a fake one.
 * ------------------------------------------------------------------ */

.aieo-c-steps { display: flex; align-items: center; gap: 0; margin: 0 0 18px; padding: 0; list-style: none; }

.aieo-c-step { display: flex; align-items: center; gap: 8px; flex: 1 1 0; min-width: 0; }
.aieo-c-step:last-child { flex: 0 0 auto; }

.aieo-c-step-dot {
	flex: 0 0 auto;
	width: 26px;
	height: 26px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	border-radius: var(--aieo-radius-pill, 999px);
	background: var(--aieo-muted, #f4f4f5);
	color: var(--aieo-muted-fg, #71717a);
	font-size: var(--aieo-text-xs, 12px);
	font-weight: 600;
}

.aieo-c-step-label {
	font-size: var(--aieo-text-xs, 12px);
	color: var(--aieo-muted-fg, #71717a);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.aieo-c-step-bar { flex: 1 1 auto; height: 2px; margin: 0 8px; background: var(--aieo-border, #ececee); min-width: 12px; }

.aieo-c-step.is-done .aieo-c-step-dot { background: var(--aieo-success, #22c55e); color: var(--aieo-success-fg, #fff); }
.aieo-c-step.is-done .aieo-c-step-bar { background: var(--aieo-success, #22c55e); }
.aieo-c-step.is-current .aieo-c-step-dot { background: var(--aieo-primary, #3b82f6); color: var(--aieo-primary-fg, #fff); }
.aieo-c-step.is-current .aieo-c-step-label { color: var(--aieo-foreground, #09090b); font-weight: 500; }

/* A bare progress bar, for where a stepper is too much furniture. */
.aieo-c-progress { height: 6px; border-radius: var(--aieo-radius-pill, 999px); background: var(--aieo-muted, #f4f4f5); overflow: hidden; }
.aieo-c-progress-fill { display: block; height: 100%; background: var(--aieo-primary, #3b82f6); transition: width .2s ease; }

/* ---------------------------------------------------------------------
 * Repeat — a block answered once per THING.
 *
 * Form 20's five-slot manual unroll is what this replaces: hidden product ids,
 * a rating per slot and four tick boxes per slot, 30 fields to say one thing
 * five times. ⚠️ And the ids ran out of order — slot 2's checkboxes (130-133)
 * come BEFORE slot 1's (138-141) — which is why the legacy reader has to key on
 * the admin label and never on id order.
 * ------------------------------------------------------------------ */

.aieo-c-repeat { display: flex; flex-direction: column; gap: 12px; }

.aieo-c-repeat-item {
	position: relative;
	padding: 14px;
	border: 1px solid var(--aieo-border, #ececee);
	border-radius: var(--aieo-radius-lg, 8px);
	background: var(--aieo-card, #fff);
}

.aieo-c-repeat-head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 10px;
	margin: 0 0 10px;
	font-size: var(--aieo-text-sm, 13px);
	font-weight: 500;
}

.aieo-c-repeat-foot { margin-top: 4px; }

/* ---------------------------------------------------------------------
 * The card a question set sits in.
 * ------------------------------------------------------------------ */

.aieo-c-card {
	padding: 16px;
	background: var(--aieo-card, #fff);
	border: 1px solid var(--aieo-border, #ececee);
	border-radius: var(--aieo-radius-lg, 8px);
	color: var(--aieo-card-fg, #09090b);
}

.aieo-c-card + .aieo-c-card { margin-top: 14px; }

.aieo-c-card-h { margin: 0 0 4px; font-size: var(--aieo-text-base, 14px); font-weight: 600; }
.aieo-c-card-d { margin: 0 0 14px; font-size: var(--aieo-text-xs, 12px); color: var(--aieo-muted-fg, #71717a); }

.aieo-c-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 16px; }

/* ---------------------------------------------------------------------
 * Motion, only where it is wanted.
 * ------------------------------------------------------------------ */

@media ( prefers-reduced-motion: reduce ) {
	.aieo-c-btn,
	.aieo-c-input,
	.aieo-c-textarea,
	.aieo-c-select,
	.aieo-c-scale-opt,
	.aieo-c-progress-fill { transition: none; }
}

/* ---------------------------------------------------------------------
 * The storefront questionnaire.
 *
 * Everything above is sized for the ADMIN, because the control gallery was
 * this layer's first consumer: 11-14px, tight rhythm, a card that sits in a
 * settings column. Dropped onto a shop page it lands next to the theme's own
 * headings and WooCommerce's order table and reads as fine print — the
 * questions look like footnotes to the receipt rather than a thing being
 * asked.
 *
 * The lift is done by REDEFINING THE TYPE TOKENS on this scope, not by
 * restating font sizes on thirty control rules. Every control already reads
 * `var(--aieo-text-sm)` and friends, so one block moves the whole layer and
 * keeps the admin gallery exactly where it was. Anything that needs a real
 * exception is below, and there are only three.
 * ------------------------------------------------------------------ */

.aieo-survey {
	--aieo-text-2xs: 12px;
	--aieo-text-xs: 14px;
	--aieo-text-sm: 15px;
	--aieo-text-base: 16px;

	/* The confirmation page puts this directly under the site nav, so it
	   needs its own air; without it the card's border reads as part of the
	   header. */
	margin: 40px 0 32px;
	padding: 28px 24px;
	line-height: 1.5;
}

/* ── The header, which lives OUTSIDE the card ──────────────────────────
 * It has to introduce the questionnaire at the size of the PAGE. Inside
 * the card it inherited the control scale and the invitation to answer
 * came out smaller than the answers.
 * Sized in `em` off an explicit root so it tracks the theme's body copy
 * instead of fighting it. */
.aieo-survey-head {
	margin: 44px 0 0;
	font-size: 16px;
	line-height: 1.45;
}

.aieo-survey-title {
	margin: 0 0 10px;
	font-size: 1.9em;
	line-height: 1.2;
	font-weight: 700;
}

.aieo-survey-lead {
	margin: 0;
	font-size: 1.15em;
	line-height: 1.5;
	opacity: 0.85;
}

/* The card follows its own header, so it does not need the full gap. */
.aieo-survey-head + .aieo-survey { margin-top: 18px; }

@media ( max-width: 600px ) {
	.aieo-survey-head { margin-top: 30px; font-size: 15px; }
	.aieo-survey-title { font-size: 1.6em; }
	.aieo-survey-head + .aieo-survey { margin-top: 14px; }
}

/* Section headings, which are the page's rhythm once it is scrolling.
 * The size is a custom property so the operator can set it per site from the
 * Questionnaires screen; the value here is the fallback, not a default that
 * has to be restated in PHP. */
.aieo-survey .aieo-c-card-h {
	margin: 30px 0 14px;
	padding-top: 18px;
	border-top: 1px solid var(--aieo-border, #ececee);
	font-size: var(--aieo-survey-section, 19px);
	line-height: 1.3;
	font-weight: 600;
}

/* The question itself, whether it is a plain label or a fieldset legend. */
.aieo-survey .aieo-c-label,
.aieo-survey .aieo-c-group > legend {
	font-size: var(--aieo-survey-question, 16px);
	line-height: 1.4;
}

/* The answers themselves: segmented points, radio and checkbox rows. */
.aieo-survey .aieo-c-scale-opt,
.aieo-survey .aieo-c-choice-item,
.aieo-survey .aieo-c-select,
.aieo-survey .aieo-c-input,
.aieo-survey .aieo-c-textarea {
	font-size: var(--aieo-survey-option, 15px);
}

/* Everything that EXPLAINS rather than asks: the scale's end captions, a
 * question's help line, a choice's sub-label. These were 11-12px, which on a
 * storefront is the size print goes to be ignored. */
.aieo-survey .aieo-c-help,
.aieo-survey .aieo-c-scale-ends,
.aieo-survey .aieo-c-choice-sub,
.aieo-survey .aieo-c-error {
	font-size: var(--aieo-survey-help, 14px);
}

/* The first one opens the questions and needs no rule above it: the card's own
 * border is already the separation. `:first-of-type` rather than a sibling
 * selector on the intro -- the intro used to live inside the card and no
 * longer does, and a rule that depends on a neighbour breaks silently the
 * moment that neighbour moves. */
.aieo-survey .aieo-c-card-h:first-of-type {
	margin-top: 0;
	padding-top: 0;
	border-top: 0;
}

.aieo-survey .aieo-c-card-d {
	margin: 0 0 4px;
	font-size: 16px;
	color: var(--aieo-muted-fg, #71717a);
}

.aieo-survey .aieo-c-field,
.aieo-survey .aieo-c-group { margin-bottom: 22px; }

.aieo-survey .aieo-c-actions { margin-top: 26px; }

@media ( max-width: 600px ) {
	.aieo-survey {
		margin: 28px 0 24px;
		padding: 20px 16px;
	}
	.aieo-survey .aieo-c-card-t { font-size: 22px; }
	.aieo-survey .aieo-c-card-h { margin-top: 24px; }
}

/* ---------------------------------------------------------------------
 * The ranking grip on touch.
 *
 * `touch-action: none` is what lets a pointer drag start instead of the
 * browser claiming the gesture as a scroll — and it is scoped to the GRIP
 * so the rest of the list, and the page, scroll normally. A nine-item
 * ranking that swallowed vertical scrolling would be worse than one that
 * only reorders by button.
 * ------------------------------------------------------------------ */

.aieo-c-rank-grip {
	touch-action: none;
	cursor: grab;
	/* A decorative pair of dots is a 6px target. Padding makes it a thumb. */
	padding: 6px 4px;
	margin: -6px -4px;
}

.aieo-c-rank-item.is-dragging .aieo-c-rank-grip { cursor: grabbing; }

@media ( pointer: coarse ) {
	.aieo-c-rank-grip { padding: 10px 8px; margin: -10px -8px; }
}

/* ---------------------------------------------------------------------
 * The thank-you that replaces the questionnaire once it is answered.
 *
 * It is the ONLY thing left where a 29-question form used to be, and it sits
 * directly under the site header on the confirmation page. Sized and spaced
 * to be read as the answer to "did that work?", not as a footnote.
 *
 * The size is set on the PARAGRAPH, not inherited from the card: the two
 * render paths (server notice(), ajax) used to put different inner elements
 * here and only one of them inherited anything.
 * ------------------------------------------------------------------ */

.aieo-survey-done {
	margin: 56px 0 40px;
	padding: 36px 28px;
	text-align: center;
}

.aieo-survey-done-msg {
	margin: 0;
	font-size: 24px;
	line-height: 1.35;
	font-weight: 600;
	color: var(--aieo-card-fg, #09090b);
}

@media ( max-width: 600px ) {
	.aieo-survey-done { margin: 36px 0 28px; padding: 26px 18px; }
	.aieo-survey-done-msg { font-size: 20px; }
}
