/**
 * TSF Forms — base styling.
 *
 * Aliases the canonical token layer (Tylers-Code/css/tsf-tokens.css, enqueued at
 * priority 1) with var() fallbacks, so this stylesheet renders correctly even if
 * it is ever loaded somewhere the tokens are not. Never hardcode a brand colour
 * here — the Elementor kit is the authoritative palette and the tokens mirror it.
 */

/*
 * These aliased --tsff-* names used to point at a --tsf-color-* namespace
 * that never existed in Tylers-Code/css/tsf-tokens.css — every one of them
 * silently fell through to its hardcoded fallback. That's why labels rendered
 * near-black (the --tsf-color-text fallback, sized for a light theme) against
 * this site's actual dark page background: the real token, --tsf-text, was
 * never being read at all. Wired to the tokens that actually exist now.
 */
.tsf-form {
	--tsff-fg: var(--tsf-text-strong, #F2F2F2);
	--tsff-muted: var(--tsf-text-muted, #8A8A8A);
	--tsff-border: var(--tsf-line, #3F3F3F);
	--tsff-bg: #fff; /* inputs are deliberately light-on-dark for legibility; no dark-theme surface token fits an input field */
	--tsff-input-fg: #1a1a1a; /* typed text inside the light input background — --tsff-fg is near-white for the dark page bg and is invisible on --tsff-bg */
	--tsff-accent: var(--tsf-red-solid, #BB0000);
	--tsff-error: var(--tsf-red, #FF0000);
	--tsff-radius: var(--tsf-radius-md, 10px);
	--tsff-gap: var(--tsf-space-6, 1rem);

	display: flex;
	flex-direction: column;
	gap: var(--tsff-gap);
	max-width: 46rem;
	color: var(--tsff-fg);
}

/*
 * Side-by-side fields on tablet/desktop. Opt-in per row via
 * `'class' => 'tsf-form-row--half'` on a field definition — two consecutive
 * half rows sit side by side through ordinary grid auto-placement, no extra
 * wrapper markup needed. Everything else defaults to spanning both columns,
 * so this is silent for any form that doesn't use the class. Mobile stays
 * single-column (the flex layout above) — matches this site's documented
 * "mobile max-width: 600px" breakpoint in tsf-tokens.css.
 */
@media (min-width: 641px) {
	.tsf-form {
		/* row/column gap both already come from the unconditional `gap` above —
		   grid respects it exactly like flex did, nothing to re-declare here. */
		display: grid;
		grid-template-columns: repeat(2, 1fr);
		align-items: start;
	}

	/* Every direct child spans both columns by default — hidden inputs
	   (nonce, honeypot, etc.) are unaffected since they don't lay out at all. */
	.tsf-form > * {
		grid-column: 1 / -1;
	}

	.tsf-form > .tsf-form-row--half {
		grid-column: span 1;
	}
}

/* ── the honeypot ──────────────────────────────────────────────────────────
 * Positioned off-screen rather than display:none. Some autofill engines and
 * scrapers treat display:none as a signal worth probing; an absolutely
 * positioned element is simply not where anyone is looking. It is already
 * tabindex="-1" and aria-hidden, so nothing can reach it by keyboard or AT.
 * Do not "tidy" this into display:none — that reintroduces the bug this
 * whole approach exists to avoid.
 */
.tsf-form-hp {
	position: absolute !important;
	left: -9999px !important;
	top: auto !important;
	width: 1px !important;
	height: 1px !important;
	overflow: hidden !important;
}

/* ── rows ─────────────────────────────────────────────────────────────────── */

.tsf-form-row {
	display: flex;
	flex-direction: column;
	gap: 0.35rem;
}

.tsf-form-row[hidden] {
	display: none;
}

.tsf-form-label {
	font-weight: 600;
	line-height: 1.3;
}

.tsf-form-req {
	color: var(--tsff-accent);
}

.tsf-form-desc {
	margin: 0;
	font-size: 0.875rem;
	color: var(--tsff-muted);
}

.tsf-form-error {
	margin: 0;
	font-size: 0.875rem;
	font-weight: 600;
	color: var(--tsff-error);
}

/* ── controls ─────────────────────────────────────────────────────────────── */

.tsf-form input[type="text"],
.tsf-form input[type="email"],
.tsf-form input[type="url"],
.tsf-form input[type="tel"],
.tsf-form input[type="number"],
.tsf-form input[type="date"],
.tsf-form select,
.tsf-form textarea {
	width: 100%;
	padding: 0.6rem 0.75rem;
	font: inherit;
	color: var(--tsff-input-fg);
	background: var(--tsff-bg);
	border: 1px solid var(--tsff-border);
	border-radius: var(--tsff-radius);
	/* Stops iOS Safari zooming the viewport on focus at <16px. */
	font-size: max(1rem, 16px);
}

.tsf-form textarea {
	resize: vertical;
	min-height: 6rem;
}

.tsf-form :is(input, select, textarea):focus-visible {
	outline: 2px solid var(--tsff-accent);
	outline-offset: 1px;
}

.tsf-form-row.is-invalid :is(input, select, textarea) {
	border-color: var(--tsff-error);
}

/* ── grouped options ──────────────────────────────────────────────────────── */

.tsf-form-options {
	display: flex;
	flex-direction: column;
	gap: 0.4rem;
	margin: 0;
	padding: 0;
	border: 0;
}

.tsf-form-options legend {
	padding: 0;
	margin-bottom: 0.35rem;
	font-weight: 600;
}

.tsf-form-option,
.tsf-form-consent {
	display: flex;
	align-items: flex-start;
	gap: 0.5rem;
	line-height: 1.4;
	cursor: pointer;
}

.tsf-form-option input,
.tsf-form-consent input {
	/* Nudge the box onto the first line's optical centre. */
	margin-top: 0.2em;
	flex: 0 0 auto;
}

/* ── sections + static content ────────────────────────────────────────────── */

.tsf-form-section {
	margin-top: 0.5rem;
	padding-top: var(--tsff-gap);
	border-top: 1px solid var(--tsff-border);
}

.tsf-form-section:first-child {
	margin-top: 0;
	padding-top: 0;
	border-top: 0;
}

.tsf-form-section-title {
	margin: 0 0 0.25rem;
	font-size: 1.15rem;
}

.tsf-form-section-desc {
	margin: 0;
	color: var(--tsff-muted);
}

.tsf-form-html {
	font-size: 0.9375rem;
}

.tsf-form-section[hidden],
.tsf-form-html[hidden] {
	display: none;
}

/* ── messages ─────────────────────────────────────────────────────────────── */

.tsf-form-summary,
.tsf-form-success,
.tsf-form-notice {
	padding: 0.85rem 1rem;
	border-radius: var(--tsff-radius);
	border: 1px solid var(--tsff-border);
}

.tsf-form-summary {
	border-color: var(--tsff-error);
}

.tsf-form-summary p,
.tsf-form-success p:last-child {
	margin: 0;
}

.tsf-form-summary:focus-visible,
.tsf-form-success:focus-visible {
	outline: 2px solid var(--tsff-accent);
	outline-offset: 2px;
}

/* ── signature pad ────────────────────────────────────────────────────────── */

.tsf-form-signature__pad {
	display: block;
	width: 100%;
	max-width: 100%;
	height: auto;
	/* Fixed aspect ratio keeps the canvas's on-screen size predictable at any
	   viewport width — the JS coordinate math (tsf-forms.js) is written to
	   track whatever size this resolves to, but a stable ratio is still what
	   keeps the pad from looking squashed on narrow screens. */
	aspect-ratio: 600 / 180;
	background: #fff;
	border: 1px solid var(--tsff-border);
	border-radius: var(--tsff-radius);
	cursor: crosshair;
	/* touch-action: none is set again in JS (belt and braces — the JS value is
	   the one that actually matters for gesture handling) so drawing works even
	   if this stylesheet fails to load for some reason. */
	touch-action: none;
}

.tsf-form-signature__pad:focus-visible {
	outline: 2px solid var(--tsff-accent);
	outline-offset: 1px;
}

.tsf-form-signature__row {
	display: flex;
	align-items: center;
	justify-content: space-between;
	margin-top: 0.35rem;
}

.tsf-form-signature__hint {
	font-size: 0.8125rem;
	color: var(--tsff-muted);
}

.tsf-form-signature__clear {
	padding: 0.3rem 0.75rem;
	font: inherit;
	font-size: 0.8125rem;
	color: var(--tsff-fg);
	background: transparent;
	border: 1px solid var(--tsff-border);
	border-radius: var(--tsff-radius);
	cursor: pointer;
}

.tsf-form-signature__clear:hover {
	border-color: var(--tsff-accent);
}

/* Client-side "you haven't signed yet" state — set by tsf-forms.js when a
   required pad is empty at submit time. The server's own required-field
   message (rendered on the row after a PRG redirect) is the fallback if JS
   never runs; this exists purely so a JS-enabled signer sees it instantly
   instead of waiting on a round trip. */
.tsf-form-signature--empty .tsf-form-signature__pad {
	border-color: var(--tsff-error);
}

.tsf-form-signature--empty .tsf-form-signature__hint {
	color: var(--tsff-error);
	font-weight: 600;
}

.tsf-form-signature--empty .tsf-form-signature__hint::after {
	content: ' — please sign above';
}

/* ── file uploads ─────────────────────────────────────────────────────────────
 *
 * The native control is kept — a custom drop zone would mean re-implementing
 * keyboard access, the file picker, and the "no file chosen" label the browser
 * already localises. Only the parts that clash with a dark form are restyled:
 * the input's own chrome, and ::file-selector-button, which otherwise renders
 * as a light-grey system button on a near-black background.
 */

.tsf-form input[type="file"] {
	width: 100%;
	padding: 0.55rem 0.75rem;
	font: inherit;
	font-size: max(1rem, 16px);
	color: var(--tsff-input-fg);
	background: var(--tsff-bg);
	border: 1px solid var(--tsff-border);
	border-radius: var(--tsff-radius);
}

.tsf-form input[type="file"]::file-selector-button {
	margin-right: 0.75rem;
	padding: 0.35rem 0.75rem;
	font: inherit;
	color: var(--tsff-fg);
	background: transparent;
	border: 1px solid var(--tsff-border);
	border-radius: calc(var(--tsff-radius) / 2);
	cursor: pointer;
}

.tsf-form input[type="file"]::file-selector-button:hover {
	border-color: var(--tsff-accent);
}

.tsf-form-row.is-invalid input[type="file"] {
	border-color: var(--tsff-error);
}

.tsf-form-file__limits,
.tsf-form-file__hint {
	margin: 0.35rem 0 0;
	font-size: 0.85em;
	color: var(--tsff-muted);
}

/* The "we still have your file" confirmation after a failed submission. It is
 * deliberately louder than a hint: someone looking at a form full of errors
 * needs to see that the one thing that took them real effort is still safe. */
.tsf-form-file__kept {
	margin: 0.5rem 0 0;
	padding: 0.5rem 0.7rem;
	font-size: 0.9em;
	border: 1px solid var(--tsff-border);
	border-left: 3px solid var(--tsff-accent);
	border-radius: calc(var(--tsff-radius) / 2);
}

.tsf-form-file__size {
	color: var(--tsff-muted);
}

/* ── submitting overlay ───────────────────────────────────────────────────────
 * Appended to <body>, not inside .tsf-form, so it can't read that element's
 * scoped --tsff-* aliases. The root-level --tsf-* tokens are still in scope
 * (tsf-tokens.css sets them on :root), so those are what it uses. Same job as
 * .hd-busy in tsf-haunt-dibs — see the note in tsf-forms.js for why this isn't
 * shared code.
 */
.tsf-form-busy {
	position: fixed;
	inset: 0;
	z-index: 11000;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 1.5rem;
	background: rgba(0, 0, 0, 0.82);
}

.tsf-form-busy__box {
	width: 100%;
	max-width: 26rem;
	padding: 1.875rem 1.625rem;
	text-align: center;
	background: var(--tsf-bg, #131313);
	border: 1px solid var(--tsf-line, #3F3F3F);
	border-radius: var(--tsf-radius-md, 10px);
	box-shadow: 0 24px 70px rgba(0, 0, 0, 0.6);
}

.tsf-form-busy__spinner {
	width: 46px;
	height: 46px;
	margin: 0 auto 1.125rem;
	border: 4px solid rgba(255, 0, 0, 0.25);
	border-top-color: var(--tsf-red, #FF0000);
	border-radius: 50%;
	animation: tsf-form-spin 0.8s linear infinite;
}

.tsf-form-busy__title {
	margin-bottom: 0.5rem;
	font-size: 1.0625rem;
	font-weight: 700;
	color: var(--tsf-text-strong, #F2F2F2);
}

.tsf-form-busy__note {
	font-size: 0.875rem;
	line-height: 1.55;
	color: var(--tsf-text, #CBCBCB);
}

@keyframes tsf-form-spin {
	to {
		transform: rotate(360deg);
	}
}

/* The spinner is the only thing saying "still working", so it must not stop
   outright for reduced-motion — it slows down instead, matching dibs.css. */
@media (prefers-reduced-motion: reduce) {
	.tsf-form-busy__spinner {
		animation-duration: 2.4s;
	}
}

/* ── submit ───────────────────────────────────────────────────────────────── */

.tsf-form-actions {
	display: flex;
	gap: 0.75rem;
}

/*
 * The Elementor kit styles bare <button> and <a> aggressively; these selectors
 * are specific enough to win without !important. See the site-header notes for
 * the kit's specificity numbers if this ever needs revisiting.
 */
.tsf-form .tsf-form-actions button.tsf-form-submit {
	padding: 0.7rem 1.5rem;
	font: inherit;
	font-weight: 700;
	color: #fff;
	background: var(--tsff-accent);
	border: 0;
	border-radius: var(--tsff-radius);
	cursor: pointer;
}

.tsf-form .tsf-form-actions button.tsf-form-submit:hover {
	filter: brightness(1.1);
}

.tsf-form .tsf-form-actions button.tsf-form-submit:disabled {
	opacity: 0.6;
	cursor: not-allowed;
}
