/**
 * Product-page configuration form.
 *
 * Layout, spacing and state for the form and the frame dialog. Colour and type
 * are mostly left to `currentColor` and the theme here, and `product.css`
 * dresses both in the shop front's tokens on the product page, which is the one
 * page this file is loaded on (`StorefrontModule::enqueue()`).
 *
 * The shapes it does set (radii, the dialog's shadow and backdrop, the focus
 * treatment) come from `tokens.css`, which loads on every page, so the form
 * holds to `docs/design-standards.md` even before `product.css` arrives. Its
 * old `--pod-gap` and `--pod-border` locals are gone: the second was never
 * read, and the first is the space scale's 16.
 */

.pod-form {
	margin: 1.5rem 0;
}

.pod-field {
	border: 0;
	margin: 0 0 var( --pod-near );
	padding: 0;
}

.pod-label {
	display: block;
	font-weight: 600;
	margin-bottom: 0.5rem;
	padding: 0;
}

.pod-sublabel {
	display: block;
	font-size: 0.8125rem;
	margin-bottom: 0.25rem;
	opacity: 0.75;
}

/* --- Options ----------------------------------------------------------- */

.pod-options {
	display: flex;
	flex-direction: column;
	gap: 0.5rem;
}

.pod-option {
	align-items: center;
	border: 1px solid;
	border-color: color-mix(in srgb, currentColor 20%, transparent);
	border-radius: var( --pod-radius );
	cursor: pointer;
	display: flex;
	gap: 0.625rem;
	padding: 0.625rem 0.75rem;
}

.pod-option:hover {
	border-color: color-mix(in srgb, currentColor 45%, transparent);
}

.pod-option:has( input:checked ) {
	border-color: currentColor;
	border-width: 2px;
	padding: calc( 0.625rem - 1px ) calc( 0.75rem - 1px );
}

/* The one focus ring, on the card, when its radio has keyboard focus. */
.pod-option:has( input:focus-visible ) {
	outline: var( --pod-focus-width ) solid var( --pod-accent );
	outline-offset: var( --pod-focus-offset );
}

/*
 * The number fields get a focus treatment of their own.
 *
 * Measured, not assumed: on focus the theme changed these from a 1px solid
 * #e2e2e2 border to a 1px *dotted* #e2e2e2 border — the same colour, the same
 * width, and about 1.27:1 against the white field. That is not a focus
 * indicator anybody can see, on the two fields that decide what the customer
 * is buying. This is the standard's field focus: the border turns accent and
 * thickens by a 1px ring, with a transparent outline kept for Windows'
 * forced-colours mode, which drops box shadows.
 *
 * Scoped to the typed fields on purpose: the radios and checkboxes already get
 * a ring from the rule above, drawn on their `.pod-option` wrapper, and a
 * second outline on the input inside it would double up.
 */
.pod-field input[type="number"]:focus,
.pod-field input[type="text"]:focus {
	border-color: var( --pod-accent );
	border-style: solid;
	box-shadow: 0 0 0 1px var( --pod-accent );
	outline: 2px solid transparent;
}

.pod-option__label {
	flex: 1;
}

.pod-option__meta {
	font-size: 0.8125rem;
	opacity: 0.7;
}

/* An option the chosen material cannot take. Dimmed rather than removed, so
   the layout does not jump and the customer can see it exists. */
.pod-option.is-unavailable {
	cursor: not-allowed;
	opacity: 0.4;
}

/* --- Size -------------------------------------------------------------- */

.pod-presets {
	display: flex;
	flex-wrap: wrap;
	gap: 0.375rem;
	margin-bottom: 0.75rem;
}

/*
 * Every ghost control here says `color: inherit`, and that is not decoration.
 *
 * They have no background, a hairline border drawn from `currentColor`, and the
 * theme's own type — the intent being that they inherit the page's colour so the
 * plugin never looks bolted on. But a `<button>` does not inherit colour by
 * default, and Astra sets `button { color: #fff }` for its filled buttons. So
 * removing the background without setting the colour left white text and a white
 * border on a white page, and every one of these was invisible until hovered,
 * which restored the theme's background.
 *
 * `color: inherit` takes the colour from the surrounding element rather than the
 * button default, which is what the intent actually requires.
 *
 * **And it has to hold while the pointer is on them**, which for a long time it
 * did not. Astra also emits
 *
 *     button:focus, button:hover, .ast-button:hover, … {
 *         color: #ffffff;
 *         background-color: var( --ast-global-color-1 );
 *         border-color: var( --ast-global-color-1 );
 *     }
 *
 * and `button:hover` is one class and one element, which beats a bare
 * `.pod-preset`. So every one of these turned into a filled blue theme button
 * under the pointer — and the *selected* size turned *invisible*, because its own
 * `[aria-pressed]` rule is two classes and wins the background back, then paints
 * it as `color-mix( currentColor 12%, … )` with `currentColor` now white. White
 * text, white fill, white border: the one control telling the customer which size
 * they are buying vanished at exactly the moment they clicked it.
 *
 * The guard below is written as `button.pod-preset` rather than with an ancestor
 * so it travels with the component, and at one class plus one element plus a
 * state it outranks the theme cleanly instead of tying and depending on which
 * stylesheet happens to load second.
 */
.pod-preset {
	background: none;
	color: inherit;
	border: 1px solid;
	border-color: color-mix(in srgb, currentColor 20%, transparent);
	border-radius: var( --pod-radius-pill );
	cursor: pointer;
	font: inherit;
	font-size: 0.875rem;
	padding: 0.3125rem 0.75rem;
}

/*
 * The ghost controls, holding their own colour in every state. See above.
 */
button.pod-preset:hover,
button.pod-preset:focus,
button.pod-framing__more:hover,
button.pod-framing__more:focus,
button.pod-framer__close:hover,
button.pod-framer__close:focus {
	background-color: transparent;
	color: inherit;
}

button.pod-preset:hover {
	border-color: currentColor;
}

button.pod-framing__more:hover,
button.pod-framing__more:focus {
	border-color: transparent;
}

/*
 * The size the form is currently on.
 *
 * Drawn from `aria-pressed` rather than a class of its own, so the state a
 * screen reader is told and the state a sighted customer sees cannot come
 * apart — there is one fact and one place it is written.
 *
 * Filled rather than merely outlined, because `:hover` already owns the full
 * border and the two would otherwise be indistinguishable on the button under
 * the cursor — which is, inconveniently, the one just clicked.
 */
/*
 * Repeated for the hovered and focused cases so the fill survives the guard
 * above, which has to clear the background for the unselected ones.
 */
.pod-preset[aria-pressed='true'],
button.pod-preset[aria-pressed='true']:hover,
button.pod-preset[aria-pressed='true']:focus {
	background-color: color-mix(in srgb, currentColor 12%, transparent);
	border-color: currentColor;
	font-weight: 600;
}

.pod-dimensions {
	align-items: end;
	display: flex;
	gap: 0.5rem;
}

.pod-dimension {
	flex: 1;
	min-width: 0;
}

.pod-dimension input {
	width: 100%;
}

.pod-dimension__times {
	line-height: 2.4;
	opacity: 0.5;
}

.pod-hint {
	font-size: 0.8125rem;
	margin: 0.5rem 0 0;
	opacity: 0.7;
}

/* --- Summary ----------------------------------------------------------- */

.pod-summary {
	border-top: 1px solid;
	border-color: color-mix(in srgb, currentColor 15%, transparent);
	margin-top: 1.25rem;
	padding-top: 1rem;
}

.pod-total {
	align-items: baseline;
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	margin-bottom: 0.875rem;
}

.pod-total__label {
	font-weight: 600;
}

.pod-total__value {
	font-size: 1.5rem;
	font-weight: 700;
}

.pod-total__unit {
	font-size: 0.875rem;
	opacity: 0.7;
}

/*
 * The standard's error notice (§5, Notices): the danger wash, a 3px danger bar
 * on the left, square on that side and rounded on the other.
 */
.pod-error {
	background: var( --pod-danger-wash );
	border-left: 3px solid var( --pod-danger );
	border-radius: 0 var( --pod-radius ) var( --pod-radius ) 0;
	color: var( --pod-ink );
	font-size: 0.9375rem;
	line-height: 1.5;
	margin: 0 0 0.875rem;
	padding: var( --pod-near ) var( --pod-apart );
}

/*
 * Why the total is not what the size suggests.
 *
 * A note, not an error: nothing has gone wrong and the price beside it is
 * correct and buyable — the same distinction `.pod-error` is kept separate for.
 *
 * `[hidden]` is honoured explicitly. This file has no blanket rule that would
 * out-rank it today, but `.pod-hint` above sets `margin` on a bare class and it
 * would take one `display` declaration on a neighbouring selector to make this
 * element visible with nothing in it — which is precisely how
 * `.pod-viz__empty[hidden]` went wrong twice.
 */
.pod-note {
	font-size: 0.8125rem;
	margin: 0 0 0.875rem;
	opacity: 0.75;
}

.pod-note[hidden] {
	display: none;
}

.pod-cta[disabled] {
	cursor: not-allowed;
	opacity: 0.5;
}

@media ( min-width: 40em ) {
	.pod-options {
		flex-direction: row;
		flex-wrap: wrap;
	}

	.pod-option {
		flex: 1 1 calc( 50% - 0.25rem );
	}
}

/* ---------------------------------------------------------------------------
   Framing
   ---------------------------------------------------------------------------
   The inline layer reuses `.pod-option`, so two curated frames land in the
   same two-up grid the materials already use at the one breakpoint below.
   --------------------------------------------------------------------------- */

.pod-swatch {
	align-items: center;
	gap: 0.5rem;
}

/* The frame itself, as a colour or a photograph. */
.pod-swatch__chip {
	background-position: center;
	background-size: cover;
	border: 1px solid color-mix(in srgb, currentColor 25%, transparent);
	border-radius: var( --pod-radius-sm );
	flex: 0 0 auto;
	height: 1.75rem;
	width: 1.75rem;
}

/* "No frame" gets a diagonal rather than an empty box, so it reads as a
   deliberate choice and not as a picture that failed to load. */
.pod-swatch__chip--none {
	background-image: linear-gradient(
		to top right,
		transparent calc(50% - 1px),
		currentColor calc(50% - 1px),
		currentColor calc(50% + 1px),
		transparent calc(50% + 1px)
	);
	opacity: 0.5;
}

.pod-framing__outer,
.pod-framing__cleared {
	font-size: 0.875rem;
	margin: 0.5rem 0 0;
}

/* A notice, not an error: the price beside it is correct and buyable. */
.pod-framing__cleared,
.pod-framer__note,
.pod-framer__reason {
	opacity: 0.8;
}

.pod-framing__more {
	background: none;
	color: inherit;
	border: 0;
	cursor: pointer;
	font: inherit;
	margin-top: 0.5rem;
	padding: 0;
	text-decoration: underline;
	text-underline-offset: 0.25em;
}

/* --- The customizer ------------------------------------------------------ */

/*
 * The standard's dialog (`docs/design-standards.md` §5, the same values as
 * `.pod-dialog`): radius-xl, the lifted shadow, and a width that leaves the page
 * gutter either side. `94vw` left 12px a side on a phone against the page's
 * 20px, so the dialog stood wider than everything behind it.
 */
.pod-framer__dialog {
	background: var( --pod-surface );
	border: 0;
	border-radius: var( --pod-radius-xl );
	box-shadow: var( --pod-shadow-lift );
	box-sizing: border-box;
	color: var( --pod-ink );
	max-height: 92vh;
	max-width: min( 44rem, calc( 100vw - 2 * var( --pod-gutter ) ) );
	padding: 0;
	width: 100%;
}

/*
 * Head, a scrolling body, and a foot that stays put.
 *
 * As a plain block the dialog itself was what scrolled once its content passed
 * the 92vh cap (the browser gives a modal `overflow: auto`), so the foot, with
 * the total and Done, scrolled out of sight with everything else. A column with
 * the body as the only part allowed to shrink keeps the head and foot on screen.
 * Only while open: a closed `<dialog>` must stay `display: none`.
 */
.pod-framer__dialog[open] {
	display: flex;
	flex-direction: column;
	overflow: hidden;
}

.pod-framer__dialog[open] .pod-framer__head,
.pod-framer__dialog[open] .pod-framer__foot {
	flex: none;
}

.pod-framer__dialog[open] .pod-framer__body {
	flex: 1 1 auto;
	min-height: 0;
}

/* Ink, not black, behind every dialog. */
.pod-framer__dialog::backdrop {
	background: var( --pod-scrim );
}

/* The standard's head and foot: 16px by 24, a line between them and the body. */
.pod-framer__head,
.pod-framer__foot {
	align-items: center;
	display: flex;
	gap: var( --pod-near );
	justify-content: space-between;
	padding: var( --pod-near ) var( --pod-apart );
}

.pod-framer__head {
	border-bottom: 1px solid var( --pod-line );
}

.pod-framer__foot {
	border-top: 1px solid var( --pod-line );
	flex-wrap: wrap;
}

/* The card heading: a dialog's title is one (§3). */
.pod-framer__title {
	font-size: var( --pod-h3-size );
	font-weight: 800;
	letter-spacing: -0.01em;
	line-height: 1.3;
	margin: 0;
	text-wrap: balance;
}

.pod-framer__close {
	background: none;
	color: inherit;
	border: 0;
	cursor: pointer;
	font-size: 1.5rem;
	line-height: 1;
	padding: 0.25rem 0.5rem;
}

.pod-framer__body {
	overflow-y: auto;
	padding: var( --pod-apart );
}

.pod-framer__group + .pod-framer__group {
	margin-top: var( --pod-apart );
}

/* The standard's group label: 0.9375rem/700 in ink, 8px above its choices. */
.pod-framer__legend {
	color: var( --pod-ink );
	font-size: 0.9375rem;
	font-weight: 700;
	letter-spacing: 0;
	line-height: 1.3;
	margin: 0 0 var( --pod-tight );
}

.pod-framer__choices {
	display: flex;
	flex-direction: column;
	gap: 0.375rem;
}

.pod-framer__sums {
	display: flex;
	flex-wrap: wrap;
	gap: 0.25rem 1rem;
}

/* The foot is the one place the total must stay visible while the customer
   scrolls a long list of mouldings. */
.pod-framer__total strong {
	font-size: 1.125rem;
}

@media (min-width: 40em) {
	.pod-framer__choices {
		display: grid;
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

/* Glazing is a sheet, not a colour: a pale pane with a highlight across it,
   which is what acrylic and glass actually look like on a wall. */
.pod-swatch__chip--clear {
	background: linear-gradient(
		135deg,
		color-mix(in srgb, currentColor 6%, transparent) 40%,
		color-mix(in srgb, currentColor 18%, transparent) 50%,
		color-mix(in srgb, currentColor 6%, transparent) 60%
	);
}

/*
 * What a material is for, under its name.
 *
 * Quieter than the label and on its own line, because it is the half that
 * decides and the half that is longest: "13oz Scrim" and "18oz Blockout" are
 * indistinguishable to anybody who does not already print banners, and the
 * sentence under them is the only thing in the row that answers which to pick.
 */
.pod-option__for {
	display: block;
	margin-top: 0.125rem;
	font-size: 0.8125rem;
	font-weight: 400;
	opacity: 0.7;
}

/*
 * Top-align a row once its label can be two lines.
 *
 * The options were centred, which was right when every label was one line. With
 * a sentence under the name the label grows and the radio and the price drift to
 * the middle of it, leaving the price beside the second line of prose rather
 * than beside the thing it prices. Only rows that actually carry a description
 * are changed, so every other option group is untouched.
 */
.pod-option:has( .pod-option__for ) {
	align-items: start;
}

/*
 * And the price stays on its own line rather than being squeezed by the prose.
 */
.pod-option:has( .pod-option__for ) .pod-option__meta {
	white-space: nowrap;
}

/*
 * Reduced motion. Nothing here animates of itself, but the theme gives every
 * `button` and field a colour transition, and these are the form's buttons.
 */
@media ( prefers-reduced-motion: reduce ) {
	.pod-option,
	.pod-preset,
	.pod-framing__more,
	.pod-framer__close,
	.pod-field input {
		transition: none;
	}
}
