/*
 * The form's own styles: enough to be usable and correct, not a theme.
 *
 * Logical properties throughout (margin-inline, padding-inline, border-inline-start)
 * rather than left/right. An Arabic or Hebrew site then lays out correctly with no
 * -rtl.css to write and no second file to keep in step (ULTRAPLAN §14.4).
 *
 * Everything a client's theme is likely to have an opinion about — typeface, brand
 * colour, button shape — is left to inherit or exposed as a custom property, because the
 * alternative is a specificity war on somebody else's site.
 */

.dfe-form {
	--dfe-gap: 1.25rem;
	--dfe-radius: 6px;

	/*
	 * WCAG 1.4.11 Non-text Contrast (AA) asks for 3:1 between a control's boundary and what
	 * is behind it, and the edge of a text input is the criterion's own worked example. The
	 * lighter grey this used to be measured 1.95:1 on white: a box a low-vision visitor
	 * cannot find is a question they never answer. No axe rule checks this one — it is
	 * measured from computed styles in tests/a11y instead.
	 */
	--dfe-border: #8a8a94;
	--dfe-focus: #1a5fd0;
	--dfe-error: #a4161a;
	--dfe-muted: #5a5a66;

	/* Surface palette, themeable. Every theme overrides these as a bundle whose
	   contrast ratios were computed when the bundle was designed — free-form theming
	   is exactly the accent colour, nothing else. */
	--dfe-paper: #fff;
	--dfe-track: #e3e3e8;
	--dfe-tint: #eef4fd;
	--dfe-on-accent: #fff;

	display: flex;
	flex-direction: column;
	gap: var(--dfe-gap);
	max-inline-size: 40rem;
}

/*
 * The attribute must win. Any rule of ours or of the theme that gives a step or a field a
 * display value would otherwise leave it on screen while the runtime believes it is gone,
 * which is how a visitor ends up answering a question the server is about to discard.
 */
.dfe-form [hidden] {
	display: none !important;
}

.dfe-step {
	border: 0;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: var(--dfe-gap);
}

.dfe-step__legend {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 0.75rem;
	padding: 0;
	inline-size: 100%;
}

/*
 * Focus lands here on every step change, so it has to be visible when it does.
 *
 * `:focus` and not `:focus-visible`, unlike every other rule in this file. These two
 * elements are `tabindex="-1"`: they are only ever focused by script and can never be
 * reached by Tab, so the stray-ring-on-click problem `:focus-visible` exists to solve
 * cannot happen here. What can happen is the opposite — whether `:focus-visible` matches a
 * programmatically focused element with no role is a per-engine heuristic, and the two
 * moments this form most needs to show where focus went are the step change and the error
 * summary. Delegating those to a heuristic is how a visitor ends up with focus somewhere
 * invisible.
 */
.dfe-step__legend:focus,
.dfe-form__errors:focus {
	outline: 2px solid var(--dfe-focus);
	outline-offset: 3px;
}

/*
 * Both are scrolled into view by .focus(), which aligns to the viewport edge — underneath
 * any sticky header, and a sticky header is close to universal in the WordPress themes this
 * plugin ships into. WCAG 2.4.11 Focus Not Obscured (AA). Exposed as a custom property so a
 * theme with a taller bar can say so instead of forking the stylesheet.
 */
.dfe-step__legend,
.dfe-form__errors {
	scroll-margin-block-start: var(--dfe-scroll-offset, 6rem);
}

.dfe-step__title {
	font-size: 1.25rem;
	font-weight: 600;
}

.dfe-step__progress {
	color: var(--dfe-muted);
	font-size: 0.875rem;
}

.dfe-field {
	display: flex;
	flex-direction: column;
	gap: 0.375rem;
}

.dfe-field--hidden {
	display: none;
}

.dfe-field__label {
	font-weight: 600;
	font-size: var(--dfe-question-size, inherit);
	color: var(--dfe-question-color, inherit);
}

.dfe-field__required {
	font-weight: 400;
	color: var(--dfe-muted);
}

.dfe-field__description {
	margin: 0;
	color: var(--dfe-muted);
	font-size: 0.875rem;
}

/*
 * :empty rather than a class the runtime toggles. An error node that is present but says
 * nothing must take no space, and tying that to a class means every path that clears an
 * error has to remember to clear the class too.
 */
.dfe-field__error:empty,
.dfe-form__errors:empty {
	display: none;
}

.dfe-field__error {
	margin: 0;
	color: var(--dfe-error);
	font-size: 0.875rem;
}

.dfe-form__errors {
	margin: 0;
	padding: 0.75rem 1rem;
	border-inline-start: 4px solid var(--dfe-error);
	background: #fdf0f0;
	color: var(--dfe-error);
}

.dfe-input {
	/*
	 * Without this the field is 100% of its container PLUS 1.5rem of padding and 2px of
	 * border, so on a theme that does not set border-box globally the form scrolls sideways
	 * at 320px — WCAG 1.4.10 Reflow. The rest of this file is written not to depend on a
	 * theme; this was the one place it did, and it is the one that breaks the layout rather
	 * than the styling.
	 */
	box-sizing: border-box;
	inline-size: 100%;
	padding: 0.625rem 0.75rem;
	border: 1px solid var(--dfe-border);
	border-radius: var(--dfe-radius);
	background: var(--dfe-paper);
	color: inherit;
	font: inherit;

	/*
	 * iOS Safari zooms the whole page when a focused input computes below 16px, and it
	 * does not zoom back out. On a conversational form that fires on the first question.
	 * The widget's answer-size control feeds the var; the 16px floor outranks it.
	 */
	font-size: max(var(--dfe-answer-size, 1rem), 16px);
}

.dfe-input:focus-visible {
	outline: 2px solid var(--dfe-focus);
	outline-offset: 1px;
}

.dfe-input[aria-invalid='true'] {
	border-color: var(--dfe-error);
}

.dfe-choices {
	border: 0;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 0.375rem;
}

.dfe-choice {
	display: flex;
	align-items: center;
	gap: 0.5rem;
}

.dfe-choice__input {
	/*
	 * WCAG 2.5.8 Target Size (Minimum) is 24x24 CSS pixels, and a default checkbox is 13.
	 *
	 * The floor is in pixels because the criterion is in pixels. `1.5rem` alone is 24px only
	 * while the root stays at 16, and WordPress themes routinely ship `html { font-size:
	 * 87.5% }` — at a 14px root the same declaration computes to 21px and the target stops
	 * conforming on somebody else's site. Same idiom as the font-size floor on .dfe-input.
	 */
	inline-size: max(1.5rem, 24px);
	block-size: max(1.5rem, 24px);
	flex: none;
}

.dfe-choice__label {
	font-weight: 400;
}

.dfe-nav {
	display: flex;
	flex-wrap: wrap;
	gap: 0.75rem;
	margin-block-start: 0.5rem;
}

.dfe-nav button {
	min-block-size: 2.75rem;
	padding-inline: 1.25rem;
	border: 1px solid var(--dfe-border);
	border-radius: var(--dfe-radius);
	background: var(--dfe-paper);
	color: inherit;
	font: inherit;
	cursor: pointer;
}

/*
 * Scoped through .dfe-nav so this outweighs `.dfe-nav button` above. Written as a bare
 * class it loses on specificity — one class against a class plus an element — and the
 * primary buttons keep the grey ring they are meant to drop, on every site, silently.
 */
.dfe-nav .dfe-nav__next,
.dfe-nav .dfe-nav__submit {
	border-color: transparent;
	background: var(--dfe-focus);
	color: var(--dfe-on-accent);
}

.dfe-nav button:focus-visible {
	outline: 2px solid var(--dfe-focus);
	outline-offset: 2px;
}

.dfe-noscript {
	margin: 0;
	padding: 0.75rem 1rem;
	border-inline-start: 4px solid var(--dfe-muted);
	background: #f3f3f5;
}

/*
 * The step that arrives fades in. Only once the runtime has taken over: before that every
 * step is on screen at once and animating them would be noise.
 */
.dfe-form--enhanced .dfe-step {
	animation: dfe-arrive 220ms ease-out;
}

@keyframes dfe-arrive {
	from {
		opacity: 0;
		transform: translateY(8px);
	}
}

/*
 * "Reduce" means substitute, not remove: MDN's own guidance replaces transform-based
 * motion with an opacity fade rather than dropping the transition, because a change that
 * happens with no transition at all is harder to follow, not easier.
 */
@media (prefers-reduced-motion: reduce) {
	@keyframes dfe-arrive {
		from {
			opacity: 0;
		}
	}
}

/*
 * While the request is in flight. The button already disabled itself; dimming the form
 * says "in progress" without hiding anything, and pointer-events stays on so a visitor
 * can still select and copy their own answers.
 */
.dfe-form--sending {
	opacity: 0.7;
}

/*
 * What replaces the form after a confirmed capture. It receives focus, so it needs a
 * visible boundary for the focus indicator to trace and enough contrast to read as the
 * page's answer rather than leftover chrome.
 */
.dfe-success {
	padding: var(--dfe-gap, 1.25rem);
	border: 2px solid #2e7d32;
	border-radius: var(--dfe-radius, 6px);
	background: #f1f8f2;
	color: #1e4620;
	font-weight: 600;
}

.dfe-success:focus {
	outline: 3px solid var(--dfe-focus, #1a5fd0);
	outline-offset: 2px;
}

/* ================= Progress bar (both modes) ================= */

/*
 * Fill driven by --dfe-progress, which the runtime recomputes from the same
 * progress() result as the announced "Paso 2 de 6" — one source, two renderings.
 * A gradient has no logical direction, so this is the one declaration in the file
 * that assumes LTR; an RTL site gets a bar that fills the "wrong" way, not a broken
 * one. Swap to a scaled inner element if an RTL client ever materialises.
 */
.dfe-form__bar {
	block-size: 4px;
	border-radius: 999px;
	background: linear-gradient(90deg, var(--dfe-focus) var(--dfe-progress, 0%), var(--dfe-track) 0);
}

/* A preview does not progress. */
.dfe-form--stacked .dfe-form__bar {
	display: none;
}

/* ================= Conversational skin ================= */

/*
 * One question per screen deserves a screen: the question carries the visual
 * weight a heading would, the input is a line to write on rather than a box to
 * fill, choices are cards you tap. Scoped away from the stacked render — the
 * builder preview exists to show structure compactly, not to feel like typing.
 */

.dfe-form--conversational:not(.dfe-form--stacked) {
	min-block-size: min(60vh, 30rem);
	justify-content: center;
}

/* The authored step title becomes a kicker: the big text on screen is the question. */
.dfe-form--conversational:not(.dfe-form--stacked) .dfe-step__title {
	font-size: 0.8125rem;
	font-weight: 650;
	letter-spacing: 0.07em;
	text-transform: uppercase;
	color: var(--dfe-muted);
}

.dfe-form--conversational:not(.dfe-form--stacked) .dfe-step__description {
	font-size: 1.0625rem;
	line-height: 1.5;
}

.dfe-form--conversational:not(.dfe-form--stacked) .dfe-field__label {
	font-size: var(--dfe-question-size, clamp(1.375rem, 1.1rem + 1.5vw, 1.75rem));
	font-weight: 650;
	line-height: 1.3;
}

.dfe-form--conversational:not(.dfe-form--stacked) .dfe-field__description {
	font-size: 1rem;
}

/*
 * A line to write on. Element+class so it outweighs .dfe-input without touching
 * textareas and selects, where a bare underline reads as broken rather than as an
 * invitation. The line keeps the compliant border colour (3:1, WCAG 1.4.11) and
 * the focus outline stays: a colour-only change of a 2px line is not an indicator
 * the a11y gate — or a glaring sun — can be trusted to see.
 */
.dfe-form--conversational:not(.dfe-form--stacked) input.dfe-input {
	border: 0;
	border-block-end: 2px solid var(--dfe-border);
	border-radius: 0;
	background: transparent;
	padding-inline: 0;
	font-size: max(var(--dfe-answer-size, 1.25rem), 18px);
}

.dfe-form--conversational:not(.dfe-form--stacked) input.dfe-input:focus-visible {
	border-block-end-color: var(--dfe-focus);
	outline-offset: 4px;
}

.dfe-form--conversational:not(.dfe-form--stacked) textarea.dfe-input,
.dfe-form--conversational:not(.dfe-form--stacked) select.dfe-input {
	font-size: max(1.125rem, 17px);
}

/* Choices as cards. Without :has() support the card simply keeps its resting look. */
.dfe-form--conversational:not(.dfe-form--stacked) .dfe-choice {
	border: 1px solid var(--dfe-border);
	border-radius: 10px;
	padding: 0.75rem 1rem;
	transition: border-color 120ms ease-out, background-color 120ms ease-out;
}

.dfe-form--conversational:not(.dfe-form--stacked) .dfe-choice:hover {
	border-color: var(--dfe-focus);
}

.dfe-form--conversational:not(.dfe-form--stacked) .dfe-choice:has(.dfe-choice__input:checked) {
	border-color: var(--dfe-focus);
	background: var(--dfe-tint);
	box-shadow: inset 0 0 0 1px var(--dfe-focus);
}

.dfe-form--conversational:not(.dfe-form--stacked) .dfe-choice__label {
	font-size: 1.0625rem;
}

/* The Enter affordance belongs to the one-question rhythm; grouped screens drop it. */
.dfe-nav__hint {
	display: none;
}

.dfe-form--conversational:not(.dfe-form--stacked) .dfe-nav__hint {
	display: inline;
	align-self: center;
	color: var(--dfe-muted);
	font-size: 0.8125rem;
}

/* ================= The question's illustration ================= */

.dfe-field__image {
	max-inline-size: 100%;
	block-size: auto;
	max-block-size: 280px;
	object-fit: contain;
	object-position: left center;
	border-radius: 10px;
	align-self: flex-start;
}

/* ================= Curated themes ================= */

/*
 * A theme is a surface-palette bundle whose ratios were computed when it was
 * designed, not knobs. Ratios noted per declaration; the floor is 4.5:1 for text,
 * 3:1 for control boundaries (WCAG 1.4.3 / 1.4.11). The admin's accent colour
 * arrives as an inline --dfe-focus on the form element, which beats these class
 * defaults — by design: the accent is the one free choice.
 */

.dfe-theme--warm {
	--dfe-border: #83796d;   /* 3.6:1 on the cream card */
	--dfe-muted: #6b6257;    /* 5.3:1 */
	--dfe-track: #e8dfd0;
	--dfe-tint: #f3e9da;
	--dfe-paper: #fffdf9;

	background: #faf6f0;
	color: #2a2723;          /* 13.5:1 */
	border: 1px solid #e5dccb;
	border-radius: 16px;
	padding: clamp(1.25rem, 4vw, 2.5rem);
}

.dfe-theme--midnight {
	--dfe-border: #8b90a0;   /* 4.9:1 on the dark card */
	--dfe-muted: #a9adbb;    /* 7.3:1 */
	--dfe-track: #2c3038;
	--dfe-tint: #223047;
	--dfe-paper: #1f2229;
	--dfe-error: #ff8b92;    /* 6.5:1 */

	/* Lighter accent than the light-theme default: #1a5fd0 measures 2.4:1 against
	   this card, below the 3:1 a focus ring needs. Dark text on it, not white. */
	--dfe-focus: #6ea8fe;
	--dfe-on-accent: #0b0d10;

	background: #16181d;
	color: #e9eaf0;          /* 14.8:1 */
	border-radius: 16px;
	padding: clamp(1.25rem, 4vw, 2.5rem);
}

.dfe-theme--midnight .dfe-form__errors {
	background: #38191c;
	color: #ffb3b8;
}

.dfe-theme--midnight .dfe-noscript {
	background: #1f2229;
}
