/*
 * ═════════════════════════════════════════════════════════════════════════════
 * VIDEOS — the plate, the popup and the gate
 *
 * Loaded on the videos archive and on a single video (see
 * fluent_commerce_ds_enqueue()), after blog.css, which is where the card and the
 * listing come from. The archive IS the blog index — same grid, same cards, same
 * head — so nothing here restyles any of that. This file adds three things and
 * changes one:
 *
 *   .fc-videoplate    the 16/9 box a video is watched from: a still, a play
 *                     button, and an iframe once somebody asks for one
 *   .fc-videomodal    the popup the archive's cards open into
 *   .fc-videogate     the email form a gated video sits behind
 *
 * and the one change is a play badge on a video card's figure, drawn entirely
 * with pseudo-elements so the card markup stays the blog's.
 *
 * There is no design export for any of this — the brief was "use the Blog index
 * design for now" — so every value here is the design system's own: the card's
 * 1px rules and ink ramp, .fc-btn's 48/10 geometry on the form, the event page's
 * white-well fields, and the section scale for the spacing. Nothing invented but
 * the arrangement.
 *
 * See assets/ds/watch.js and inc/ds-video.php.
 * ══════════════════════════════════════════════════════════════════════════ */

/* ─────────────────────────────────────────────────────────────────────────────
 * THE CARD'S PLAY BADGE
 *
 * Two pseudo-elements on the figure: a ring, and the triangle inside it as a
 * mask. On the figure and not on the card, because the badge belongs to the
 * image — and because .fc-card__figure is the one element in the card that is
 * always present, with or without a featured image.
 *
 * .fc-card--video only exists when the popup is on the page (see
 * fluent_commerce_ds_video_card_attrs()), so a video card in a related-posts row
 * elsewhere on the site does not advertise a control it does not have.
 * ────────────────────────────────────────────────────────────────────────── */
body.fc-ds .fc-card--video .fc-card__figure {
	position: relative;
}

/* The ring. Bone on a 40% ink veil rather than solid white: it has to read on a
   dark frame grab and on a bright one, and a plain white disc blows out of a
   pale still. */
body.fc-ds .fc-card--video .fc-card__figure::before {
	content: "";
	position: absolute;
	top: 50%;
	left: 50%;
	width: 64px;
	height: 64px;
	margin: -32px 0 0 -32px;
	border: var(--stroke-1) solid var(--fc-bone-a80);
	border-radius: var(--radius-pill);
	background: var(--fc-ink-a40);
	/* The badge is not a target — the whole card is the link. */
	backdrop-filter: blur(2px);
	transition: background var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out);
}

/*
 * The triangle. A mask in the bone rather than a glyph, because the card's markup
 * is fixed and this is the one place in the theme where an icon has to come from
 * CSS. Same geometry as the play_arrow path in inc/ds-icons.php, minus its ring —
 * the ::before above is the ring.
 */
body.fc-ds .fc-card--video .fc-card__figure::after {
	content: "";
	position: absolute;
	top: 50%;
	left: 50%;
	width: 22px;
	height: 22px;
	/* 1px right of centre: a triangle's optical centre sits left of its bounding
	   box, so a mathematically centred one reads as too far left inside a ring. */
	margin: -11px 0 0 -10px;
	background-color: var(--fc-bone);
	mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='22' height='22' viewBox='0 0 22 22'%3E%3Cpath d='M6 3.6 L17.5 11 L6 18.4 Z' fill='%23000'/%3E%3C/svg%3E") center / 22px 22px no-repeat;
	transition: background-color var(--dur-base) var(--ease-out);
}

/* The card's own hover is a colour move on its rule and meta; the badge joins in
   by filling to violet. Nothing scales — the design's cards do not move. */
body.fc-ds .fc-card--video:hover .fc-card__figure::before,
body.fc-ds .fc-card--video:focus-visible .fc-card__figure::before {
	background: var(--fc-violet);
	border-color: var(--fc-violet);
}

/* ─────────────────────────────────────────────────────────────────────────────
 * THE PLATE
 *
 * The same box in three places: the single video's hero, the popup's stage, and
 * (with no player URL) the still above a gate form. 16/9 because that is what
 * both providers deliver; the featured images are 16/10 like every other card
 * image, so `cover` crops a sliver off the top and bottom rather than letterboxing.
 * ────────────────────────────────────────────────────────────────────────── */
body.fc-ds .fc-videoplate {
	position: relative;
	display: block;
	width: 100%;
	aspect-ratio: 16 / 9;
	/* Black, not the card's ink veil: this is a video box, and every frame that
	   lands in it will be letterboxed against something. */
	background-color: var(--fc-black);
	background-size: cover;
	background-position: center;
	overflow: hidden;
}

/* The button fills the plate — the whole still is the target, which is what a
   visitor will aim at anyway. The ring below is drawn by ::before, so the button
   itself has nothing of its own to see. */
body.fc-ds .fc-videoplate__play {
	position: absolute;
	inset: 0;
	display: grid;
	place-items: center;
	width: 100%;
	appearance: none;
	padding: 0;
	border: 0;
	background: transparent;
	color: var(--fc-bone);
	cursor: pointer;
}

/*
 * A veil behind the glyph, and deliberately NOT a ring: play_arrow draws its own
 * ring (see inc/ds-icons.php), and a bordered disc behind it would put two circles
 * round one triangle. So this has no edge at all — it is contrast insurance, there
 * so a bone glyph still reads when the frame grab underneath it is a white studio
 * wall. 34 of glyph in a 78 veil, which is the card badge's own proportion.
 */
body.fc-ds .fc-videoplate__play::before {
	content: "";
	position: absolute;
	top: 50%;
	left: 50%;
	width: 78px;
	height: 78px;
	margin: -39px 0 0 -39px;
	border-radius: var(--radius-pill);
	background: var(--fc-ink-a40);
	backdrop-filter: blur(2px);
	transition: background var(--dur-base) var(--ease-out);
}

/* The veil is what fills on hover; the glyph stays bone, so the move is the same
   colour move the card badge makes. */
body.fc-ds .fc-videoplate__play:hover::before,
body.fc-ds .fc-videoplate__play:focus-visible::before {
	background: var(--fc-violet);
}

/* Above the veil, and inheriting the button's colour so it needs no rule of its
   own beyond the stacking. The icon set draws it stroked in currentColor. */
body.fc-ds .fc-videoplate__glyph {
	position: relative;
	z-index: 1;
	display: block;
}

/*
 * The locked state's glyph: the same mark at 40% so it reads as "this is a video"
 * without reading as "press this". It is aria-hidden and not a button, because the
 * thing to press when a video is gated is the form's own submit.
 */
body.fc-ds .fc-videoplate__locked {
	position: absolute;
	inset: 0;
	display: grid;
	place-items: center;
	color: var(--fc-bone-a40);
}

/*
 * And the real button is not there while it is locked.
 *
 * The button is RENDERED in the locked state — see the note in
 * fluent_commerce_ds_video_plate() — because a visitor whose Pardot pass is remembered is
 * unlocked by watch.js, and the alternative was watch.js building a button, which means a
 * second copy of the play_arrow SVG living in a .js file. So the markup is always there
 * and this is what makes the state: display:none rather than opacity or
 * pointer-events, because a hidden control must be out of the tab order too — a keyboard
 * user should not be able to reach a play button for a video that will not play.
 */
body.fc-ds .fc-videoplate--locked .fc-videoplate__play {
	display: none;
}

/* The iframe, once watch.js has made one. Also the <noscript> fallback's, which
   is why this is not scoped to .fc-videoplate--playing. */
body.fc-ds .fc-videoplate__frame {
	position: absolute;
	inset: 0;
	display: block;
	width: 100%;
	height: 100%;
	border: 0;
}

/* ─────────────────────────────────────────────────────────────────────────────
 * THE SINGLE VIDEO PAGE
 *
 * The plate stands where the featured image would, so it takes the hero's own
 * spacing. blog.css puts that margin on .fc-post__hero; this restates it rather
 * than sharing a selector, because the two are alternatives and a shared class
 * would suggest they can appear together.
 * ────────────────────────────────────────────────────────────────────────── */
body.fc-ds .fc-videowatch {
	margin-top: var(--sp-54);
}

/* Gated: the still, then the form. Not side by side — the still is 16/9 and the
   form is one row of controls, so a two-up would leave a column of air beside a
   button. */
body.fc-ds .fc-videowatch--gated {
	display: flex;
	flex-direction: column;
	gap: var(--sp-32);
}

/*
 * The gate on the single page sits in the reading column's measure, not the
 * plate's full width: it is a sentence and a field, and a 68ch cap is what makes
 * it read as one. The plate above it stays full-width deliberately — the video is
 * the page, the form is the ask.
 */
body.fc-ds .fc-videowatch--gated .fc-videogate {
	max-width: 68ch;
}

/* ─────────────────────────────────────────────────────────────────────────────
 * THE POPUP
 *
 * A fixed overlay, not a <dialog> — see the note in fluent_commerce_ds_video_modal().
 * z-index 300 clears the sticky nav's 120 and the skip link's 200.
 * ────────────────────────────────────────────────────────────────────────── */
body.fc-ds .fc-videomodal {
	position: fixed;
	inset: 0;
	z-index: 300;
	display: flex;
	align-items: center;
	justify-content: center;
	/* The gutter the dialog can never cross, so it never touches a phone's edges.
	   env() keeps it clear of a notch in landscape, which is exactly the orientation
	   somebody will turn to watch a video in. */
	padding: max(var(--sp-24), env(safe-area-inset-top)) max(var(--sp-24), env(safe-area-inset-right)) max(var(--sp-24), env(safe-area-inset-bottom)) max(var(--sp-24), env(safe-area-inset-left));
	opacity: 0;
	transition: opacity var(--dur-base) var(--ease-out);
}

/* 16 down the sides on a phone. The gutter still exists — the dialog still never touches an
   edge — but 24 twice over plus the gate's own 24 twice over was 96px of a 390px screen spent
   on air, and one of the things inside is 304px wide and cannot shrink. The vertical gutter
   is unchanged: it is what keeps a dialog off a notch. See .fc-videomodal__gate below. */
@media only screen and (max-width: 600px) {
	body.fc-ds .fc-videomodal {
		padding-right: max(var(--sp-16), env(safe-area-inset-right));
		padding-left: max(var(--sp-16), env(safe-area-inset-left));
	}
}

/*
 * The attribute, set one frame after `hidden` comes off, is what the transition
 * moves to. Two states rather than one because a transition needs a `from` that
 * was painted, and an element revealed and restyled in the same frame has none.
 */
body.fc-ds .fc-videomodal[data-open="1"] {
	opacity: 1;
}

/*
 * The browser's own [hidden] is a single attribute selector and loses to the class
 * above it, which would leave a black overlay across every archive page load. The
 * same restatement every hidden region in this theme carries.
 */
body.fc-ds .fc-videomodal[hidden] {
	display: none;
}

body.fc-ds .fc-videomodal__scrim {
	position: absolute;
	inset: 0;
	background: var(--fc-ink-a93);
}

/*
 * 1080 is the point where a 16/9 stage stops gaining anything from more width on a
 * 1440 screen and starts crowding the scrim it needs to read as a layer. The
 * dialog is a column: head, then stage or form.
 */
body.fc-ds .fc-videomodal__dialog {
	position: relative;
	display: flex;
	flex-direction: column;
	width: 100%;
	max-width: 1080px;
	/* The dialog can never be taller than the viewport it is centred in; a long gate
	   form on a short landscape phone scrolls inside it rather than off it. */
	max-height: 100%;
	overflow-y: auto;
	background: var(--surface-light);
	transform: translateY(8px);
	transition: transform var(--dur-base) var(--ease-out), max-width var(--dur-base) var(--ease-out);
}

/*
 * Narrow while it is asking, wide once it is playing.
 *
 * 1080 is a player's width, and a single email field stretched across it reads as a
 * mistake — the button ends up a screen away from the words that explain it. 560 is the
 * width the field and its button want: about 60 characters of the body line above them,
 * which is where prose stops being comfortable anyway.
 *
 * data-mode is set by watch.js before the dialog is revealed, so the gate opens narrow
 * rather than snapping to it. On a successful submit the mode flips to play, and max-width
 * is in the transition above so the form widens into the video instead of cutting to it.
 */
body.fc-ds .fc-videomodal[data-mode="gate"] .fc-videomodal__dialog {
	max-width: 560px;
}

body.fc-ds .fc-videomodal[data-open="1"] .fc-videomodal__dialog {
	transform: translateY(0);
}

/*
 * NO RING ON THE DIALOG ITSELF.
 *
 * watch.js gives it tabindex="-1" and focuses it whenever there is nothing better inside to
 * focus — a video playing, or an embedded form, which is a cross-origin document this side
 * cannot reach into. That move seeds the tab trap and gives Esc something to fire on; it is
 * not a keyboard landing, and Chrome draws its own ring on a programmatic focus() all the
 * same. What that looks like is a 1080px box outlined in violet the moment a video opens.
 *
 * Suppressed HERE and nowhere else: every control inside keeps its own indicator, and the
 * close button is the first thing a Tab reaches.
 */
body.fc-ds .fc-videomodal__dialog:focus,
body.fc-ds .fc-videomodal__dialog:focus-visible {
	outline: none;
}

/* Nothing moves for anyone who has asked for that. The dialog still appears — only
   the 8px and the fade are dropped. */
@media (prefers-reduced-motion: reduce) {
	body.fc-ds .fc-videomodal,
	body.fc-ds .fc-videomodal__dialog {
		transition: none;
	}

	body.fc-ds .fc-videomodal__dialog {
		transform: none;
	}
}

body.fc-ds .fc-videomodal__head {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: var(--sp-24);
	padding: var(--sp-24);
	/* The card's rule, in the same place it sits on a card: between the meta and the
	   thing below it. */
	border-bottom: var(--stroke-1) solid var(--border-on-light);
}

/*
 * The video's title, at the card's own display setting rather than a heading size —
 * it is the same string the card was showing a moment ago, and it should look like
 * it followed the click. min-width:0 so a long title wraps instead of pushing the
 * close button off the edge.
 */
body.fc-ds .fc-videomodal__title {
	min-width: 0;
	margin: 0;
	font-family: var(--font-display);
	font-weight: var(--fw-regular);
	font-size: var(--type-h5-24);
	line-height: var(--lh-tight);
	letter-spacing: var(--ls-display);
	color: var(--text-on-light);
	text-wrap: pretty;
}

/* 44px square: the minimum comfortable touch target, and the reason the ✕ inside
   it is set smaller than the box. */
body.fc-ds .fc-videomodal__close {
	flex: none;
	display: grid;
	place-items: center;
	width: 44px;
	height: 44px;
	/* Optical: the glyph aligns to the title's cap line rather than to the box. */
	margin: -6px -6px 0 0;
	appearance: none;
	padding: 0;
	border: 0;
	background: transparent;
	font-family: var(--font-core);
	font-size: 20px;
	line-height: 1;
	color: var(--fc-ink-a60);
	cursor: pointer;
	transition: color var(--dur-fast) var(--ease-out);
}

body.fc-ds .fc-videomodal__close:hover,
body.fc-ds .fc-videomodal__close:focus-visible {
	color: var(--text-on-light);
}

/*
 * The stage. Black and 16/9 from the moment the dialog opens, carrying the card's
 * own still as a background so there is a picture in the box before the player has
 * loaded — and so the box never changes size when it does.
 */
body.fc-ds .fc-videomodal__stage {
	position: relative;
	width: 100%;
	aspect-ratio: 16 / 9;
	background-color: var(--fc-black);
	background-size: cover;
	background-position: center;
}

body.fc-ds .fc-videomodal__stage[hidden] {
	display: none;
}

/* The iframe watch.js drops in carries .fc-videoplate__frame, so it is already
   absolute inset 0 — the stage only has to be its containing block, which the
   position above makes it. */

body.fc-ds .fc-videomodal__gate {
	padding: var(--sp-32) var(--sp-24) var(--sp-54);
}

/*
 * 16 rather than 24 down the sides on a phone, which is 16px of form back.
 *
 * THE REASON IS A THIRD-PARTY BOX. This padding sits inside the scrim's own — tightened to
 * match, above — so on a 390 screen the two together left 294px of form. Where the gate is
 * an embedded Pardot form that is not enough: reCAPTCHA's widget is a FIXED 304px wide and
 * cannot be told otherwise, so it was being clipped at the right edge on the commonest phone
 * width there is. 390 less 16 and 16 twice over is 326, which clears it.
 *
 * Narrower than about 370 the sum still does not reach 304, and no padding here can fix
 * that — the frame's own stylesheet scales the widget instead. See THE CAPTCHA in
 * assets/ds/pardot-form-video.css.
 */
@media only screen and (max-width: 600px) {
	body.fc-ds .fc-videomodal__gate {
		padding-right: var(--sp-16);
		padding-left: var(--sp-16);
	}
}

body.fc-ds .fc-videomodal__gate[hidden] {
	display: none;
}

/* ─────────────────────────────────────────────────────────────────────────────
 * THE GATE FORM
 *
 * The event page's fields — white wells on the bone, 48px, radius 10 — with the
 * blog CTA's arrangement: one row, input and button side by side. Both precedents
 * are deliberate: it is the event form's surface treatment on the email CTA's
 * shape, because it asks for one thing and sits on a light panel.
 * ────────────────────────────────────────────────────────────────────────── */
body.fc-ds .fc-videogate {
	display: flex;
	flex-direction: column;
	gap: var(--sp-16);
}

body.fc-ds .fc-videogate__eyebrow {
	margin: 0;
	color: var(--fc-violet);
}

body.fc-ds .fc-videogate__body {
	margin: 0;
	font-family: var(--font-core);
	font-weight: var(--fw-medium);
	font-size: var(--type-body-18);
	line-height: var(--lh-body);
	color: var(--text-on-light-muted);
	text-wrap: pretty;
}

/* .fc-meta carries the face and the tracking; this only sets the gap to the field
   it labels, and it is a visible label rather than a hidden one because the form
   appears inside a dialog with no surrounding copy to infer it from. */
body.fc-ds .fc-videogate__label {
	display: block;
	margin-top: var(--sp-8);
	color: var(--text-on-light);
}

/* The field and the button, one row. auto on the button so it keeps .fc-btn's
   padding and the input takes the rest. */
body.fc-ds .fc-videogate__row {
	display: grid;
	grid-template-columns: 1fr auto;
	gap: 12px;
}

/* Below this the button's label and a legible field cannot both fit on one line,
   so the button takes its own row at full width. The container is the page, not
   the dialog — the dialog has no container of its own and the phone case is the
   one that matters. */
@container page (max-width: 640px) {
	body.fc-ds .fc-videogate__row {
		grid-template-columns: 1fr;
	}
}

body.fc-ds .fc-videogate__input {
	width: 100%;
	min-width: 0;
	height: 48px;
	padding: 0 16px;
	background: var(--fc-white);
	border: var(--stroke-1) solid var(--fc-ink-12);
	border-radius: var(--radius-10);
	font-family: var(--font-core);
	/* The form size — see layout.css. It matters twice over here: the zoom this
	   avoids would move the viewport under an open modal. */
	font-size: var(--fc-field-size);
	font-weight: var(--fw-medium);
	color: var(--text-on-light);
}

body.fc-ds .fc-videogate__input::placeholder {
	color: var(--fc-ink-a40);
}

/* :focus rather than :focus-visible — a click into a text field is a request to
   type, so it should show where the caret went. The event form's own call. */
body.fc-ds .fc-videogate__input:focus {
	outline: var(--stroke-1) solid var(--fc-violet);
	border-color: var(--fc-violet);
}

/* aria-invalid, which both paths already set: the server on a round trip, watch.js
   in place. No second attribute to keep in step with it. */
body.fc-ds .fc-videogate__input[aria-invalid="true"] {
	border-color: var(--fc-red);
}

/*
 * A filled button, not the outlined .fc-btn--dark: the form is the only action in
 * the dialog and an outline beside a white well disappears. Geometry is .fc-btn's
 * exactly, so the row is one height.
 */
body.fc-ds .fc-videogate__submit {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	height: 48px;
	padding: 0 22px;
	appearance: none;
	border: var(--stroke-1) solid var(--fc-ink-12);
	border-radius: var(--radius-10);
	background: var(--fc-ink-12);
	font-family: var(--font-core);
	font-size: var(--type-mono-14);
	font-weight: var(--fw-medium);
	color: var(--fc-bone);
	white-space: nowrap;
	cursor: pointer;
	transition: background var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}

body.fc-ds .fc-videogate__submit:hover,
body.fc-ds .fc-videogate__submit:focus-visible {
	background: var(--fc-violet);
	border-color: var(--fc-violet);
}

/*
 * In flight. aria-busy is what watch.js sets, so the visible state and the state a
 * screen reader is told about are the same attribute — not a class beside it that
 * could get out of step.
 */
body.fc-ds .fc-videogate__submit[aria-busy="true"] {
	background: var(--fc-ink-a40);
	border-color: transparent;
	cursor: progress;
}

/*
 * The consent statement is .fc-consent in layout.css — this form used to style its own
 * at 15px with a 12px fine print under it, which is the one form that disagreed with
 * itself. See inc/ds-consent.php.
 *
 * All that is left here is the same 8px this form already gives its email label: a
 * breath before a new thought, on top of the 16px stack gap.
 */
body.fc-ds .fc-videogate .fc-consent {
	margin-top: var(--sp-8);
}

body.fc-ds .fc-videogate__error {
	display: flex;
	align-items: center;
	gap: var(--sp-8);
	margin: 0;
	font-family: var(--font-core);
	font-weight: var(--fw-medium);
	font-size: var(--type-label-12);
	letter-spacing: var(--ls-eyebrow);
	text-transform: uppercase;
	color: var(--fc-red);
}

/* The alert region lives in the DOM permanently and carries `hidden` when there is
   nothing to say, so — as on the event form — this is load-bearing rather than
   tidy. Without it every idle page shows a red "[ ! ]" under the field. */
body.fc-ds .fc-videogate__error[hidden] {
	display: none;
}

/* The mono face exists for exactly this: a machine's own punctuation. */
body.fc-ds .fc-videogate__mark {
	font-family: var(--font-mono);
	font-variant-ligatures: none;
}

/* ─────────────────────────────────────────────────────────────────────────────
 * THE EMBEDDED GATE
 *
 * Since 2026-08-26 a gated video can be asked for by a Pardot form embedded in an
 * iframe instead of by the form above. Both are on the page in the popup and
 * exactly one is visible, so both need to be hideable — see the [hidden] rule
 * immediately below, which is not tidiness.
 *
 * There is almost nothing to style. The eyebrow and the body line are the same two
 * elements the site's own gate uses and are already styled above; the frame is
 * .fc-pardot / .fc-pardot__frame in layout.css, which gives it full width, no
 * border and color-scheme:light. Everything inside it — the field, the country
 * select, the opt-in and the button — is a document from another origin, styled by
 * assets/ds/pardot-form-video.css pasted into Pardot's layout template. No
 * selector in this file can reach it, and none tries.
 * ────────────────────────────────────────────────────────────────────────── */

/*
 * LOAD-BEARING. .fc-videogate sets display:flex, and a class selector beats the UA
 * stylesheet's [hidden] rule — so without this, hiding either gate does nothing at
 * all and a visitor gets both forms at once. It is the same reason
 * .fc-videogate__error[hidden] exists above.
 */
body.fc-ds .fc-videogate[hidden] {
	display: none;
}

/*
 * The frame's own hook, and it deliberately sets nothing.
 *
 * The 16px stack gap above it is the gap, and the pasted-in CSS gives the Pardot
 * document zero top padding so the frame's first pixel is the field's first pixel —
 * which is the only way a margin out here can mean what it says. It is here as the
 * place any future correction belongs, and so the class in
 * fluent_commerce_ds_video_pardot_gate() is not a class with nothing behind it.
 */
body.fc-ds .fc-videogate__pardot {
	width: 100%;
}
