/**
 * WS Form PRO — theme skin.
 *
 * WS Form ships two independent CSS payloads, toggled in WS Form → Settings →
 * Advanced → CSS:
 *
 *   - "Layout CSS" (css_layout: true) — still ON. The 12-column flex grid
 *     (`.wsf-grid` / `.wsf-tile` / `.wsf-{breakpoint}-{n}`), the offsets, and the
 *     show/hide rules for `.wsf-invalid-feedback`, echoed inline by the plugin.
 *     We build on it and must not fight it: the column widths carry `!important`
 *     and the breakpoints (576/768/992/1200) are the plugin's, not Tailwind's.
 *   - "Style CSS" (css_style: false) — OFF, deliberately. That one switch drops
 *     *every* internal stylesheet (base, button, checkbox, radio, file, validate,
 *     loader, datetime, tel, textarea, …), so everything below the grid is ours.
 *     This file is that everything.
 *
 * Three consequences worth knowing before editing:
 *
 *   - `.wsf-hidden { display: none !important }` lived in the plugin's base CSS
 *     and is restored below. Conditional logic mostly hides via inline
 *     `style="display:none"`, but `.wsf-hidden` still drives label/field hiding.
 *   - The dropzone and the xdsoft datepicker have no vendor skin to fall back on
 *     — WS Form styled both itself. (The picker's *external* stylesheet does
 *     still load; external CSS is not gated by the switch.)
 *   - `--wsf-gutter` must stay at the plugin's `skin_grid_gutter` (20px):
 *     `ws-form-public-file.js` reads that setting and writes it as an inline
 *     margin on every dropzone preview. Change both or neither.
 *
 * Enqueued only on pages carrying a form — see `inc/integrations/ws-form.php`.
 * Colours go through theme.json presets with literal fallbacks, as
 * `assets/archive/archive.css` does; sizes are literals with px comments,
 * because `--wp--preset--font-size--*` is unsafe inside block markup
 * (docs/styling.md).
 */

.wsf-form {
	/* Half to each side of a field wrapper, cancelled by an equal negative margin
	   on the row, so outer field edges stay flush with the article measure. */
	--wsf-gutter: 20px;
	--wsf-row-gap: 1.5rem;      /* 24px */
	--wsf-section-gap: 2.5rem;  /* 40px */

	--wsf-fg: var(--wp--preset--color--foreground, #000000);
	--wsf-ink: var(--wp--preset--color--ink, #07121c);
	--wsf-muted: var(--wp--preset--color--muted, #606060);
	--wsf-accent: var(--wp--preset--color--accent, #ffd200);
	/* Mirrors `--btn-bg-hover` on `.nomon-btn` in main.css; the hover tint has no
	   preset of its own, so keep the two in step. */
	--wsf-accent-hover: #ffdf4d;
	--wsf-surface: var(--wp--preset--color--surface, #ececec);
	--wsf-surface-alt: var(--wp--preset--color--surface-alt, #f2f2f2);
	--wsf-danger: var(--wp--preset--color--danger, #96201a);
	--wsf-danger-bg: var(--wp--preset--color--danger-bg, #fbe4e2);
	--wsf-success: var(--wp--preset--color--success, #1c7031);
	--wsf-success-bg: var(--wp--preset--color--success-bg, #e3f4e7);
	--wsf-warning: var(--wp--preset--color--warning, #a85400);
	--wsf-warning-bg: var(--wp--preset--color--warning-bg, #fdeedd);

	/* `muted` (5.9:1 on white), not `border` (#dbdbdb, 1.3:1): SC 1.4.11 wants
	   3:1 for a UI component's visible boundary, and on a form that boundary is
	   the affordance. `border` stays right for decorative rules. */
	--wsf-field-border: var(--wp--preset--color--muted, #606060);
	--wsf-transition: 0.15s ease;
	--wsf-skew: var(--skew-angle, -12deg);

	max-width: var(--article-measure, 56.25rem); /* 900px */
}

/* Join the article column. `!important` beats WP's constrained-layout
   `margin-inline: auto !important` on the wrapping group's children — the same
   offset and the same reason as the prose rule in `main.css`. */
.site-content .nomon-article .wsf-form {
	margin-inline: max(
		0px,
		calc((100% - var(--wp--style--global--content-size)) / 2)
	) auto !important;
}

.wsf-form .wsf-hidden {
	display: none !important;
}

/* Added in WS Form 1.12.x. A section whose "Display Label" is off still renders
   its `<legend>` — a `<fieldset>` needs one for its accessible name — and hides
   it with this class. It is defined only in the plugin's base CSS, which
   `css_style: false` drops, so without this rule the legend paints as a heading
   (an unnamed section shows the literal word "Section"). Visually hidden, not
   `display: none`, so the fieldset keeps its accessible name. */
.wsf-form .wsf-hidden-element {
	border: 0 !important;
	clip: rect(0, 0, 0, 0) !important;
	height: 1px !important;
	margin: -1px !important;
	overflow: hidden !important;
	padding: 0 !important;
	position: absolute !important;
	white-space: nowrap !important;
	width: 1px !important;
}

/* Only `.wsf-fields` rows bleed by half a gutter — `.wsf-sections` stays at the
   measure, which is what lands the field content boxes flush with it. */
.wsf-form .wsf-grid.wsf-fields {
	margin-inline: calc(var(--wsf-gutter) / -2);
}

.wsf-form .wsf-field-wrapper {
	padding-inline: calc(var(--wsf-gutter) / 2);
	margin-bottom: var(--wsf-row-gap);
}

.wsf-form .wsf-field-wrapper[data-type="submit"] {
	margin-bottom: 0;
	margin-top: 0.625rem;
}

.wsf-form .wsf-section {
	margin: 0;
	padding: 0;
	border: 0;
	min-width: 0; /* a flex item's min-content floor would widen the row */
}

/* Legends are headings, so they take the heading voice and the accent bar the
   page title carries. Grid + start justification sizes the track to the text so
   the bar stretches to the legend, not the column. */
.wsf-form .wsf-section > legend {
	display: grid;
	justify-content: start;
	float: none;
	width: auto;
	margin: var(--wsf-section-gap) 0 1.25rem;
	padding: 0;
	font-family: var(--wp--preset--font-family--barlow-condensed);
	font-size: 1.375rem; /* 22px */
	font-weight: 600;
	line-height: 1.15;
	text-transform: uppercase;
	color: var(--wsf-fg);
}

.wsf-form .wsf-section > legend::after {
	content: "";
	display: block;
	height: 4px;
	margin-top: 0.375rem;
	background-color: var(--wsf-accent);
	transform: skewX(var(--wsf-skew));
}

/* `:first-of-type`, not `:first-child`: conditional logic hides sections with
   inline `display: none` without removing them, and a hidden first section
   would otherwise hand the leading gap to whichever section really renders. */
.wsf-form .wsf-sections > .wsf-section:first-of-type > legend {
	margin-top: 0;
}

.wsf-form .wsf-label {
	display: block;
	margin: 0 0 0.375rem;
	font-family: var(--wp--preset--font-family--inter);
	font-size: 0.9375rem; /* 15px */
	font-weight: 600;
	line-height: 1.4;
	color: var(--wsf-fg);
}

.wsf-form .wsf-required-wrapper .wsf-text-danger {
	color: var(--wsf-danger);
	font-weight: 600;
}

.wsf-form .wsf-help {
	display: block;
	max-width: 68ch; /* help text runs to paragraphs; 900px of 13px is unreadable */
	margin-top: 0.375rem;
	font-size: 0.8125rem; /* 13px */
	line-height: 1.5;
	color: var(--wsf-muted);
}

.wsf-form .wsf-help.wsf-help-pre {
	margin-top: 0;
	margin-bottom: 0.375rem;
}

/* Matched on `.wsf-field` rather than by type: `datetime`, `tel` and `file` are
   all `input[type=text]` under the hood. The exclusions sit inside `:where()` to
   keep this at (0,2,1) — a bare `:not([type=…])` chain would take three attribute
   selectors' worth of specificity and outrank the state rules below it. */
.wsf-form input.wsf-field:not(:where([type="checkbox"], [type="radio"], [type="hidden"])),
.wsf-form textarea.wsf-field,
.wsf-form select.wsf-field {
	display: block;
	width: 100%;
	min-width: 0;
	margin: 0;
	padding: 0.6875rem 0.875rem; /* 11px 14px */
	border: 1px solid var(--wsf-field-border);
	background-color: var(--wp--preset--color--background, #ffffff);
	font-family: var(--wp--preset--font-family--inter);
	font-size: 1rem; /* 16px — below this iOS zooms the viewport on focus */
	font-weight: 400;
	line-height: 1.5;
	color: var(--wsf-fg);
	transition: border-color var(--wsf-transition), background-color var(--wsf-transition);
}

.wsf-form textarea.wsf-field {
	min-height: 8.75rem; /* 140px */
	resize: vertical;
}

.wsf-form select.wsf-field {
	appearance: none;
	-webkit-appearance: none;
	padding-inline-end: 2.25rem;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23606060' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right 0.875rem center;
	background-size: 14px;
	cursor: pointer;
}

.wsf-form input.wsf-field::placeholder,
.wsf-form textarea.wsf-field::placeholder {
	color: var(--wsf-muted);
	opacity: 1;
}

/* Ink, not the theme's usual accent: #ffd200 on a white field is 1.5:1, short of
   the 3:1 SC 1.4.11 asks of a focus indicator. Same deliberate swap
   docs/design-spec.md records for the search button's label. */
.wsf-form input.wsf-field:focus-visible,
.wsf-form textarea.wsf-field:focus-visible,
.wsf-form select.wsf-field:focus-visible {
	outline: 2px solid var(--wsf-ink);
	outline-offset: 2px;
	border-color: var(--wsf-ink);
}

.wsf-form .wsf-field:disabled {
	background-color: var(--wsf-surface-alt);
	color: var(--wsf-muted);
	cursor: not-allowed;
}

.wsf-form [data-row-checkbox],
.wsf-form [data-row-radio] {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-start;
	gap: 0 0.625rem;
	margin-bottom: 0.5rem;
}

.wsf-form [data-row-checkbox]:last-child,
.wsf-form [data-row-radio]:last-child {
	margin-bottom: 0;
}

.wsf-form input[type="checkbox"].wsf-field,
.wsf-form input[type="radio"].wsf-field {
	appearance: none;
	-webkit-appearance: none;
	flex: 0 0 auto;
	width: 18px;
	height: 18px;
	/* Optically centres on the label's first line (16px × 1.5) while
	   `align-items: flex-start` holds it there when the label wraps. */
	margin: 3px 0 0;
	border: 1px solid var(--wsf-field-border);
	background-color: var(--wp--preset--color--background, #ffffff);
	background-repeat: no-repeat;
	background-position: center;
	background-size: 12px;
	cursor: pointer;
	transition: background-color var(--wsf-transition), border-color var(--wsf-transition);
}

/* The theme squares everything, but roundness here is the affordance separating
   "pick one" from "pick any" — the carve-out the loading spinners got when radii
   were dropped site-wide. */
.wsf-form input[type="radio"].wsf-field {
	border-radius: 50%;
}

/* Ink glyph on accent: white on #ffd200 is 1.5:1. Ink on accent is 14.4:1, the
   pairing the theme's buttons already use. */
.wsf-form input[type="checkbox"].wsf-field:checked {
	background-color: var(--wsf-accent);
	border-color: var(--wsf-ink);
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2307121c' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
}

.wsf-form input[type="radio"].wsf-field:checked {
	background-color: var(--wsf-accent);
	border-color: var(--wsf-ink);
	box-shadow: inset 0 0 0 4px var(--wp--preset--color--background, #ffffff);
}

/* Keyed to the label, not the row: the label spans the field column (it must —
   see the flex note below) and *is* the click target, so highlighting exactly
   its box makes the feedback match the hit area. The row is wider still, and
   would light the box from outside anything clickable. `:has()` because the
   label follows the input, so no sibling combinator can reach back to it. */
.wsf-form input:is([type="checkbox"], [type="radio"]).wsf-field:hover:not(:where(:checked, :disabled)),
.wsf-form :is([data-row-checkbox], [data-row-radio]):has(> .wsf-label:hover)
	input:is([type="checkbox"], [type="radio"]).wsf-field:not(:where(:checked, :disabled)) {
	border-color: var(--wsf-ink);
	background-color: var(--wsf-surface);
}

.wsf-form input:is([type="checkbox"], [type="radio"]).wsf-field:checked:hover:not(:where(:disabled)),
.wsf-form :is([data-row-checkbox], [data-row-radio]):has(> .wsf-label:hover)
	input:is([type="checkbox"], [type="radio"]).wsf-field:checked:not(:where(:disabled)) {
	background-color: var(--wsf-accent-hover);
}

.wsf-form input[type="checkbox"].wsf-field:focus-visible,
.wsf-form input[type="radio"].wsf-field:focus-visible {
	outline: 2px solid var(--wsf-ink);
	outline-offset: 2px;
}

/* `flex-basis: 0` is load-bearing, not a default. The row is `flex-wrap: wrap`,
   so line breaking is decided on base sizes: at `auto` a long option measures
   wider than a narrow column and drops onto its own line *below* its own box.
   Zero-basis keeps it beside the box and lets the text wrap inside instead. */
.wsf-form [data-row-checkbox] > .wsf-label,
.wsf-form [data-row-radio] > .wsf-label {
	flex: 1 1 0;
	min-width: 0;
	margin: 0;
	font-weight: 400;
	font-size: 1rem;
	line-height: 1.5;
	cursor: pointer;
}

/* Marks the chosen option in text as well as colour — the box alone carries it
   on accent, which is the palette's weakest signal on white. Adjacent sibling,
   not `:has()`: the label always directly follows its input. */
.wsf-form .wsf-field:checked + .wsf-label {
	text-decoration: underline;
	text-underline-offset: 3px;
}

.wsf-form [data-row-checkbox] > .wsf-invalid-feedback,
.wsf-form [data-row-radio] > .wsf-invalid-feedback {
	flex: 0 0 100%;
	margin-inline-start: calc(18px + 0.625rem);
}

.wsf-form .wsf-invalid-feedback {
	margin-top: 0.375rem;
	font-size: 0.8125rem;
	line-height: 1.5;
	font-weight: 600;
	color: var(--wsf-danger);
}

/* Both gate shapes: `.wsf-validated` lands on the form after a submit attempt
   and on the field wrapper for real-time validation. */
.wsf-form.wsf-validated .wsf-field:invalid,
.wsf-form.wsf-validated .wsf-field.wsf-invalid,
.wsf-form .wsf-validated .wsf-field:invalid,
.wsf-form .wsf-validated .wsf-field.wsf-invalid {
	border-color: var(--wsf-danger);
	background-color: var(--wsf-danger-bg);
}

.wsf-form .wsf-alert {
	margin: 0 0 var(--wsf-row-gap);
	padding: 1rem 1.25rem;
	border-inline-start: 4px solid var(--wsf-muted);
	background-color: var(--wsf-surface-alt);
	font-size: 1rem;
	line-height: 1.6;
	color: var(--wsf-fg);
}

/* main.css excludes `.wsf-form` from the article prose scale, so an alert's own
   paragraphs take their rhythm here. */
.wsf-form .wsf-alert > * {
	margin-block: 0.75rem;
	font-size: inherit;
	line-height: inherit;
	font-weight: inherit;
	color: inherit;
}

.wsf-form .wsf-alert > :first-child { margin-top: 0; }
.wsf-form .wsf-alert > :last-child { margin-bottom: 0; }

.wsf-form .wsf-alert a {
	color: inherit;
	text-decoration: underline;
	text-underline-offset: 3px;
}

.wsf-form .wsf-alert.wsf-alert-success {
	border-inline-start-color: var(--wsf-success);
	background-color: var(--wsf-success-bg);
}

.wsf-form .wsf-alert.wsf-alert-danger {
	border-inline-start-color: var(--wsf-danger);
	background-color: var(--wsf-danger-bg);
}

.wsf-form .wsf-alert.wsf-alert-warning {
	border-inline-start-color: var(--wsf-warning);
	background-color: var(--wsf-warning-bg);
}

.wsf-form .wsf-alert.wsf-alert-information {
	border-inline-start-color: var(--wsf-ink);
	background-color: var(--wsf-surface);
}

/* The theme's button shape. `.nomon-btn` gets it from `transform: skewX()` plus
   an inner `<span>` carrying the counter-skew, but WS Form renders a bare
   `<button>Lähetä</button>` — so the fill rides a `::before` instead, the trick
   `.nomon-archive-pill` uses. Same shape, no markup requirement. */
.wsf-form .wsf-button {
	--wsf-button-bg: var(--wsf-accent);
	--wsf-button-bg-hover: var(--wsf-accent-hover);
	--wsf-button-fg: var(--wsf-ink);

	position: relative;
	isolation: isolate;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 0.6875rem 1.875rem; /* 11px 30px */
	border: 0;
	background: transparent;
	color: var(--wsf-button-fg);
	font-family: var(--wp--preset--font-family--barlow-condensed);
	font-size: 1.125rem; /* 18px */
	font-weight: 700;
	line-height: 1.7;
	letter-spacing: 0.5px;
	text-transform: uppercase;
	cursor: pointer;
}

.wsf-form .wsf-button::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	background-color: var(--wsf-button-bg);
	transform: skewX(var(--wsf-skew));
	transition: background-color var(--wsf-transition);
}

.wsf-form .wsf-button:hover::before,
.wsf-form .wsf-button:focus-visible::before {
	background-color: var(--wsf-button-bg-hover);
}

.wsf-form .wsf-button:focus-visible {
	outline: 2px solid var(--wsf-ink);
	outline-offset: 6px;
}

/* WS Form's per-button full-width flag, set in the form builder; both live forms
   use it. Inset by half the lean so the leaning ends land on the field column's
   edges rather than outside them (as `.nomon-archive-results__pills` does).
   52.6px is the button's box height: 30.6px line + 22px padding. */
.wsf-form .wsf-button.wsf-button-full {
	--wsf-button-slant: calc(52.6px * tan(var(--wsf-skew)) * -1);
	display: flex;
	width: calc(100% - var(--wsf-button-slant));
	margin-inline: calc(var(--wsf-button-slant) / 2);
}

.wsf-form .wsf-button:disabled {
	cursor: not-allowed;
	opacity: 0.55;
}

/* No plugin loader CSS means no spinner, so the submit lock reads on the button. */
.wsf-form.wsf-form-post-lock-progress .wsf-button {
	cursor: progress;
	opacity: 0.7;
}

/* Dropzone ships no stylesheet of its own — WS Form styled it — so this is the
   whole widget. Per-preview margins come from `ws-form-public-file.js` as inline
   styles derived from `skin_grid_gutter`; see the header note. */
.wsf-form .dropzone {
	padding: 1.75rem 1.25rem 0;
	border: 1px dashed var(--wsf-field-border);
	background-color: var(--wsf-surface-alt);
	cursor: pointer;
	transition: border-color var(--wsf-transition), background-color var(--wsf-transition);
}

.wsf-form .dropzone .dz-message {
	margin-bottom: 1.75rem;
	font-size: 0.9375rem;
	color: var(--wsf-muted);
	text-align: center;
}

.wsf-form .dropzone.dz-started .dz-message {
	display: none;
}

.wsf-form .dropzone.dz-drag-hover,
.wsf-form .dropzone:focus-within {
	border-color: var(--wsf-ink);
	border-style: solid;
	background-color: var(--wsf-surface);
}

/* The container disables pointer events so drops land on the zone; each preview
   re-enables them for its own remove control and drag handle. */
.wsf-form .dropzone .wsf-dropzonejs-previews {
	pointer-events: none;
}

.wsf-form .dropzone .wsf-dropzonejs-preview {
	position: relative;
	pointer-events: all;
	cursor: move;
}

.wsf-form .dropzone .wsf-dropzonejs-preview img {
	display: block;
	max-width: 100%;
	height: auto;
}

.wsf-form .dropzone [data-dz-name] {
	font-size: 0.8125rem;
	color: var(--wsf-fg);
	word-break: break-word;
}

.wsf-form .dropzone [data-dz-size] {
	font-size: 0.8125rem;
	color: var(--wsf-muted);
}

.wsf-form .dropzone [data-dz-remove] {
	display: inline-block;
	margin-top: 0.25rem;
	font-size: 0.8125rem;
	font-weight: 600;
	color: var(--wsf-danger);
	text-decoration: underline;
	text-underline-offset: 3px;
	cursor: pointer;
}

.wsf-form .dropzone .wsf-progress {
	height: 4px;
	margin-top: 0.5rem;
	background-color: var(--wp--preset--color--border, #dbdbdb);
	overflow: hidden;
}

.wsf-form .dropzone .wsf-progress .wsf-upload {
	height: 100%;
	background-color: var(--wsf-ink);
	transition: width var(--wsf-transition);
}

.wsf-form .dropzone .wsf-progress.wsf-progress-success .wsf-upload {
	background-color: var(--wsf-success);
}

.wsf-form .dropzone .dz-complete .wsf-progress {
	display: none;
}

/* Dropzone reuses the feedback class, which the layout CSS keeps hidden until
   validation runs — inside a preview it must always show. */
.wsf-form .dropzone .wsf-invalid-feedback {
	display: block;
}

/* The xdsoft picker's external stylesheet still loads, so this only re-tones the
   stock widget. It attaches to <body>, hence the unscoped selectors, and the
   vendor sheet sets these same properties with `!important` of its own. */
.xdsoft_datetimepicker {
	border: 1px solid var(--wp--preset--color--ink, #07121c);
	border-radius: 0;
	box-shadow: 0 6px 20px rgb(0 0 0 / 0.12);
	font-family: var(--wp--preset--font-family--inter);
}

.xdsoft_datetimepicker .xdsoft_label,
.xdsoft_datetimepicker .xdsoft_calendar th {
	font-family: var(--wp--preset--font-family--barlow-condensed);
	text-transform: uppercase;
	letter-spacing: 0.5px;
	color: var(--wp--preset--color--foreground, #000000);
	background-color: transparent;
}

.xdsoft_datetimepicker .xdsoft_calendar td {
	border-radius: 0;
}

.xdsoft_datetimepicker .xdsoft_calendar td:hover,
.xdsoft_datetimepicker .xdsoft_timepicker .xdsoft_time_box > div > div:hover {
	background-color: var(--wp--preset--color--surface, #ececec) !important;
	color: var(--wp--preset--color--foreground, #000000) !important;
}

.xdsoft_datetimepicker .xdsoft_calendar td.xdsoft_current,
.xdsoft_datetimepicker .xdsoft_timepicker .xdsoft_time_box > div > div.xdsoft_current {
	background-color: var(--wp--preset--color--accent, #ffd200) !important;
	color: var(--wp--preset--color--ink, #07121c) !important;
	box-shadow: none !important;
	font-weight: 700;
}

.xdsoft_datetimepicker .xdsoft_calendar td.xdsoft_today {
	color: var(--wp--preset--color--ink, #07121c) !important;
	font-weight: 700;
}

.xdsoft_datetimepicker .xdsoft_calendar td.xdsoft_disabled {
	color: var(--wp--preset--color--muted, #606060) !important;
	opacity: 0.4;
}

.wsf-form [data-type="turnstile"] .wsf-label {
	margin-bottom: 0.5rem;
}

@media (prefers-reduced-motion: reduce) {
	.wsf-form .wsf-field,
	.wsf-form .wsf-button::before,
	.wsf-form .dropzone,
	.wsf-form .dropzone .wsf-progress .wsf-upload {
		transition: none;
	}
}
