/* ==========================================================================
   Newsletter opt-in — v11 "Signal Dark"
   --------------------------------------------------------------------------
   The form's BEHAVIOUR is unchanged: same fields, same nonce, same honeypot,
   same time trap, same required consent, same double opt-in, same handler and
   mailer. Only its appearance is redesigned.

   What changed:

   THE JOINED CONTROL. The field and the button are one object — a single
   rounded row with the submit sitting inside its right edge — rather than an
   input with a separate button stacked beneath it. This is the shape the
   reference gives its closing form, and it is the right one: subscribing is
   one action, so it should look like one control. Below 30rem the row
   unstacks into two full-width controls, because a button inside the field at
   phone width leaves about four characters of visible email address.

   THE PILL. Corners are full-round here rather than the tile radius the
   previous build used. Everything the reader can operate on this site is a
   pill; the form is no exception.

   AMBER. The submit is the page's action colour with near-black text. White
   on amber is 2.4:1 and fails outright, so the dark ink is a contrast
   requirement rather than a stylistic preference.

   Four contexts, one component:
     default          in the sidebar panel
     --on-accent      on the closing signal panel
     inside .st-modal the dialog
     (the hero's ghost button opens the modal rather than embedding a fourth)

   The consent checkbox is drawn rather than native: a native box cannot be
   given a radius or an accent matching this palette across browsers, and
   `color-scheme: dark` alone would leave it a grey system square.
   ========================================================================== */

.st-optin {
	display: flex;
	flex-direction: column;
	gap: 1rem;
	width: 100%;
}

/* ── The joined control ───────────────────────────────────────────────
   One bordered row carrying both the input and the submit. The row owns the
   border and the focus ring; the input inside it is chromeless, so the two
   never draw competing outlines. */
.st-optin__row {
	position: relative;
	display: flex;
	align-items: center;
	gap: 0.5rem;
	padding: 0.35rem 0.35rem 0.35rem 0.4rem;
	border: 1px solid var(--line-firm);
	border-radius: var(--r-pill);
	background: var(--surface-hi);
	transition: border-color var(--speed) var(--ease), box-shadow var(--speed) var(--ease);
}

/* The ring is drawn on the ROW rather than on the input, so focusing the
   field lights the whole control. :focus-within rather than :focus-visible —
   the row is not itself focusable. */
.st-optin__row:focus-within {
	border-color: var(--amber);
	box-shadow: 0 0 0 3px var(--amber-wash);
}

.st-optin__input {
	flex: 1;
	min-width: 0;
	padding: 0.75rem 0.5rem 0.75rem 0.85rem;
	border: 0;
	background: transparent;
	color: var(--text);
	font-family: var(--font-body);
	font-size: var(--fs-small);
	line-height: 1.4;
}

.st-optin__input:focus {
	outline: none;
}

.st-optin__input::placeholder {
	color: var(--text-dim);
}

/* The browser's own invalid styling fires while the field is still being
   typed into, so it is scoped to a field the reader has already filled and
   left. The row carries the state, not the input. */
.st-optin__row:has(.st-optin__input:not(:placeholder-shown):invalid) {
	border-color: var(--flag);
}

/* ── Submit ───────────────────────────────────────────────────────────── */
.st-optin__submit {
	flex: none;
	padding: 0.8rem 1.5rem;
	border: 0;
	border-radius: var(--r-pill);
	background: var(--amber);
	color: var(--amber-ink);
	font-family: var(--font-body);
	font-size: var(--fs-small);
	font-weight: 600;
	line-height: 1;
	white-space: nowrap;
	cursor: pointer;
	transition: background var(--speed) var(--ease), transform var(--speed) var(--ease);
}

.st-optin__submit:hover,
.st-optin__submit:focus-visible {
	background: var(--amber-lift);
}

.st-optin__submit:active {
	transform: scale(0.98);
}

.st-optin__submit:disabled {
	opacity: 0.5;
	cursor: not-allowed;
	transform: none;
}

/* Phone width: the joined control unstacks. */
@media (max-width: 30rem) {
	.st-optin__row {
		flex-direction: column;
		align-items: stretch;
		gap: 0.5rem;
		padding: 0.5rem;
		border-radius: var(--r-plate);
	}

	.st-optin__input {
		padding: 0.7rem 0.85rem;
	}

	.st-optin__submit {
		width: 100%;
		padding-block: 0.85rem;
	}
}

/* ── Consent ──────────────────────────────────────────────────────────
   Required, and deliberately not pre-ticked: this is the record that the
   reader agreed, and a pre-ticked box is not consent. */
.st-optin__consent-label {
	display: flex;
	align-items: flex-start;
	gap: 0.6rem;
	cursor: pointer;
}

/* The native input stays in the DOM and focusable — it is what carries the
   `required` validation and what a screen reader announces — but is drawn
   off under the custom box. `opacity:0` rather than `display:none`, which
   would remove it from the tab order and from constraint validation. */
.st-optin__checkbox {
	position: absolute;
	width: 1.1rem;
	height: 1.1rem;
	margin: 0;
	opacity: 0;
	cursor: pointer;
}

.st-optin__consent-text {
	position: relative;
	padding-left: 1.75rem;
	color: var(--text-dim);
	font-size: var(--fs-micro);
	line-height: 1.55;
}

/* The drawn box. */
.st-optin__consent-text::before {
	content: "";
	position: absolute;
	left: 0;
	top: 0.08rem;
	width: 1.15rem;
	height: 1.15rem;
	border: 1px solid var(--line-firm);
	border-radius: 6px;
	background: var(--surface-hi);
	transition: background var(--speed) var(--ease), border-color var(--speed) var(--ease);
}

/* The tick, drawn as two borders on a rotated box rather than as an SVG or a
   glyph, so it needs no second asset. */
.st-optin__consent-text::after {
	content: "";
	position: absolute;
	left: 0.4rem;
	top: 0.26rem;
	width: 0.3rem;
	height: 0.58rem;
	border: solid var(--amber-ink);
	border-width: 0 2px 2px 0;
	transform: rotate(45deg) scale(0);
	transform-origin: center;
	transition: transform 160ms var(--ease);
}

.st-optin__checkbox:checked + .st-optin__consent-text::before {
	background: var(--amber);
	border-color: var(--amber);
}

.st-optin__checkbox:checked + .st-optin__consent-text::after {
	transform: rotate(45deg) scale(1);
}

.st-optin__checkbox:focus-visible + .st-optin__consent-text::before {
	outline: 2px solid var(--amber);
	outline-offset: 2px;
}

.st-optin__consent-text a {
	color: var(--text-muted);
	text-decoration: underline;
	text-decoration-color: var(--line-firm);
	text-underline-offset: 2px;
}

.st-optin__consent-text a:hover {
	color: var(--amber);
	text-decoration-color: currentColor;
}

/* ── The status line ──────────────────────────────────────────────────
   role="status", so it is announced when the handler writes into it. Empty
   until then, and it takes no space while empty — an always-reserved line
   under the button is a permanent gap for a message most readers never see.

   Each state carries a left rule in its own colour over a matching wash. */
.st-optin__message {
	margin: 0;
	padding: 0.7rem 0.95rem;
	border-left: 3px solid var(--line-firm);
	border-radius: 0 8px 8px 0;
	background: rgba(243, 241, 237, 0.05);
	color: var(--text-muted);
	font-size: var(--fs-meta);
	line-height: 1.5;
}

.st-optin__message:empty {
	display: none;
}

.st-optin__message.is-success {
	border-left-color: var(--ok);
	background: var(--ok-wash);
	color: var(--ok);
}

.st-optin__message.is-error {
	border-left-color: var(--flag);
	background: var(--flag-wash);
	color: var(--flag);
}

/* The honeypot. Hidden from sight and from assistive tech, but present in
   the DOM and fillable, which is the entire point — a bot that fills it is
   rejected. Not `display:none`: some bots skip those. */
.st-optin__hp {
	position: absolute !important;
	left: -9999px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

/* ── On the signal panel ──────────────────────────────────────────────
   The closing panel is already amber-washed, so the control needs to read
   against a warm ground rather than against the page. The row goes to a
   translucent well that lets the wash through, and the submit stays amber —
   it is still the page's one action, and inverting it to white here would
   make it look like a secondary control on the very block where it is the
   primary one. */
.st-optin--on-accent .st-optin__row {
	border-color: rgba(243, 241, 237, 0.2);
	background: rgba(12, 13, 17, 0.55);
}

.st-optin--on-accent .st-optin__row:focus-within {
	border-color: var(--amber);
	box-shadow: 0 0 0 3px var(--amber-tint);
}

.st-optin--on-accent .st-optin__input {
	color: var(--text);
}

.st-optin--on-accent .st-optin__input::placeholder {
	color: rgba(243, 241, 237, 0.5);
}

.st-optin--on-accent .st-optin__consent-text {
	color: rgba(243, 241, 237, 0.62);
}

.st-optin--on-accent .st-optin__consent-text::before {
	border-color: rgba(243, 241, 237, 0.28);
	background: rgba(12, 13, 17, 0.5);
}

.st-optin--on-accent .st-optin__consent-text a {
	color: rgba(243, 241, 237, 0.8);
}

.st-optin--on-accent .st-optin__consent-text a:hover {
	color: var(--amber);
}

.st-optin--on-accent .st-optin__message {
	background: rgba(12, 13, 17, 0.5);
}

/* ── The modal ────────────────────────────────────────────────────────
   Opened by any [href="#formPopup"]. A raised surface on a dark scrim,
   entering with one short rise. */
.st-modal {
	position: fixed;
	inset: 0;
	z-index: 200;
	display: grid;
	place-items: center;
	padding: var(--gutter);
}

/* optin-form.js opens and closes the dialog by toggling the `hidden`
   attribute. `display:grid` above is a class rule and therefore beats the UA
   stylesheet's `[hidden] { display: none }`, so without this the modal is
   open on every page load. Marked !important so no later display rule on
   .st-modal can reintroduce the bug. */
.st-modal[hidden] {
	display: none !important;
}

.st-modal__backdrop {
	position: absolute;
	inset: 0;
	background: rgba(6, 7, 9, 0.78);
	backdrop-filter: blur(4px);
	-webkit-backdrop-filter: blur(4px);
}

.st-modal__dialog {
	position: relative;
	width: min(31rem, 100%);
	max-height: 90vh;
	overflow-y: auto;
	padding: clamp(1.75rem, 4vw, 2.5rem);
	border: 1px solid var(--amber-edge);
	border-radius: var(--r-panel);
	background:
		radial-gradient(70% 60% at 100% 0%, rgba(229, 138, 60, 0.16), transparent 62%),
		var(--surface);
	box-shadow: var(--shade-panel);
	animation: st-modal-rise 240ms var(--ease-out) both;
}

@keyframes st-modal-rise {
	from { opacity: 0; transform: translateY(14px); }
	to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
	.st-modal__dialog { animation: none; }
}

.st-modal__close {
	position: absolute;
	top: 1rem;
	right: 1rem;
	display: grid;
	place-items: center;
	width: 2.25rem;
	height: 2.25rem;
	padding: 0;
	border: 1px solid var(--line-firm);
	border-radius: var(--r-pill);
	background: transparent;
	color: var(--text-muted);
	font-size: 1.25rem;
	line-height: 1;
	cursor: pointer;
	transition: background var(--speed) var(--ease),
	            color var(--speed) var(--ease),
	            border-color var(--speed) var(--ease);
}

.st-modal__close:hover,
.st-modal__close:focus-visible {
	border-color: var(--amber);
	color: var(--amber);
}

/* The modal's label, carrying the same dot-and-rule marker every other
   section label on the site uses. */
.st-modal__kicker {
	display: inline-flex;
	align-items: center;
	gap: 0.6rem;
	margin: 0 0 0.75rem;
	color: var(--text-muted);
	font-size: var(--fs-meta);
	font-weight: 600;
	letter-spacing: 0;
}

.st-modal__kicker::before {
	content: "";
	flex: none;
	width: 0.4rem;
	height: 0.4rem;
	border-radius: 50%;
	background: var(--amber);
	box-shadow: 0 0 0 4px var(--amber-wash);
}

.st-modal__title {
	margin: 0;
	max-width: 18ch;
	font-family: var(--font-body);
	font-size: clamp(1.625rem, 3.5vw, 2.125rem);
	font-weight: 700;
	line-height: 1.08;
	letter-spacing: var(--track-tight);
	color: var(--text);
	text-wrap: balance;
}

.st-modal__sub {
	margin: 0.85rem 0 1.75rem;
	color: var(--text-muted);
	font-size: var(--fs-small);
	line-height: 1.6;
}
