/*
 * MBForms — public styles.
 *
 * Structural rules are unscoped and byte-for-byte what 1.0 shipped: their
 * specificity is part of the contract with every theme already styling around
 * them. Everything added in 1.1 is scoped under a mode class, so a form that
 * did not ask for it sees nothing new.
 *
 * Deliberately minimal. The theme owns typography, colour and spacing scale:
 * no font declarations, no colours beyond the error state, no !important, and
 * nothing that fights a theme's own form styling. BEM under .mbf-.
 */

/*
 * Design tokens. Every value the normalise mode applies comes from one of
 * these, so a site can match its theme in a few lines instead of overriding
 * rules. Settings -> Styling writes the same properties inline.
 *
 * The defaults are inherited or neutral on purpose: normalise unifies the
 * three controls without imposing a palette.
 */
.mbf-form {
	--mbf-field-bg: transparent;
	--mbf-field-color: inherit;
	--mbf-field-border: 1px solid rgba(128, 128, 128, 0.45);
	--mbf-field-border-focus: var(--mbf-field-border);
	--mbf-field-radius: 3px;
	--mbf-field-padding: 0.5em 0.7em;
	--mbf-label-weight: 600;
	--mbf-gap: 1.25em;
	--mbf-accent: currentColor;
	--mbf-error: #b32d2e;
	--mbf-help-color: inherit;
}

.mbf-form__fields {
	display: flex;
	flex-direction: column;
	gap: var(--mbf-gap);
}

.mbf-field {
	display: flex;
	flex-direction: column;
	gap: 0.35em;
}

.mbf-field__fieldset {
	border: 0;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 0.35em;
}

.mbf-field__legend,
.mbf-field__label {
	padding: 0;
	font-weight: var(--mbf-label-weight);
}

.mbf-field__help {
	margin: 0;
	font-size: 0.9em;
	color: var(--mbf-help-color);
	opacity: 0.8;
}

.mbf-field__choices {
	display: flex;
	flex-direction: column;
	gap: 0.35em;
}

.mbf-field__choice {
	display: flex;
	align-items: baseline;
	gap: 0.5em;
}

.mbf-field__choice-label {
	font-weight: inherit;
}

.mbf-field__input {
	width: 100%;
	max-width: 100%;
	box-sizing: border-box;
}

.mbf-field__input--textarea {
	resize: vertical;
}

.mbf-field__error {
	margin: 0;
	font-size: 0.9em;
	color: var(--mbf-error);
}

.mbf-field--invalid .mbf-field__input,
.mbf-field--invalid .mbf-field__control {
	border-color: var(--mbf-error);
	outline-color: var(--mbf-error);
}

.mbf-form__messages:empty {
	display: none;
}

.mbf-form__messages {
	margin-bottom: 1em;
}

.mbf-form__messages--error {
	color: var(--mbf-error);
}

.mbf-form__actions {
	margin-top: var(--mbf-gap);
}

/* Hidden fields must not leave a gap in the flex column. */
.mbf-field--hidden,
.mbf-field[hidden] {
	display: none;
}

/* The admin preview is not submittable; make that visible without shouting. */
.mbf-form--preview {
	opacity: 0.95;
}

.mbf-form--preview .mbf-form__submit {
	cursor: not-allowed;
}

/*
 * Honeypot. Off-screen rather than display:none — some bots skip anything
 * hidden that way, which is the whole point of the field.
 */
.mbf-form__hp {
	position: absolute;
	left: -9999px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

.mbf-form__messages--success {
	font-weight: 600;
}

.mbf-form--sending .mbf-form__submit {
	opacity: 0.7;
	cursor: progress;
}

.mbf-form--done .mbf-form__fields,
.mbf-form--done .mbf-form__actions {
	display: none;
}

/*
 * Grid layout. Only active when the form asks for it with "layout": "grid";
 * a stacked form never sees any of this. Six columns divide cleanly into
 * halves, thirds and two-thirds.
 */
.mbf-form--grid .mbf-form__fields {
	display: grid;
	grid-template-columns: repeat(6, minmax(0, 1fr));
	gap: var(--mbf-gap);
	align-items: start;
}

.mbf-form--grid .mbf-field {
	grid-column: span 6;
}

.mbf-form--grid .mbf-field--width-half {
	grid-column: span 3;
}

.mbf-form--grid .mbf-field--width-third {
	grid-column: span 2;
}

.mbf-form--grid .mbf-field--width-two-thirds {
	grid-column: span 4;
}

/* Narrow screens get one column, whatever the field asked for. */
@media (max-width: 600px) {
	.mbf-form--grid .mbf-field--width-half,
	.mbf-form--grid .mbf-field--width-third,
	.mbf-form--grid .mbf-field--width-two-thirds {
		grid-column: span 6;
	}
}


/* ------------------------------------------------------------------------
 * Normalise mode.
 *
 * The problem this solves: a theme declares a selector list like
 * input[type="text"], input[type="email"], input[type="tel"] and leaves out
 * textarea and select, so those two fall back to the browser default — most
 * visibly a white background on a dark form. One declaration block applied to
 * all three makes them agree.
 *
 * Checkboxes, radios, buttons and file inputs are deliberately excluded: they
 * are not text-entry surfaces and boxing them looks broken.
 *
 * The :not() chain is repeated on select and textarea, and that is deliberate
 * rather than sloppy. Each selector in a list is weighed on its own: the input
 * arm scores (0,10,1) and a bare "textarea" scores (0,1,1), so an ordinary
 * theme rule like ".entry-content .form-wrap textarea" at (0,2,1) loses to the
 * input arm and beats the textarea arm — which is exactly how a form ends up
 * with a textarea whose border ignores the setting every other field obeys.
 *
 * Neither a type attribute nor those values exist on a select or a textarea, so
 * every :not() there matches everything and the chain changes what is selected
 * not at all. It only makes the three arms weigh the same.
 *
 * Levelling upwards rather than downwards is the point. Lowering the input arm
 * to match the others was tried and shipped in 1.3.2: it made the three agree
 * and made all of them lose to the theme, so no setting had any visible effect.
 * Reverted. The arm that already wins is left exactly as it was.
 * ---------------------------------------------------------------------- */

.mbf-form--normalize input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]):not([type="reset"]):not([type="file"]):not([type="image"]):not([type="range"]):not([type="color"]),
.mbf-form--normalize select:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]):not([type="reset"]):not([type="file"]):not([type="image"]):not([type="range"]):not([type="color"]),
.mbf-form--normalize textarea:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]):not([type="reset"]):not([type="file"]):not([type="image"]):not([type="range"]):not([type="color"]) {
	background: var(--mbf-field-bg);
	color: var(--mbf-field-color);
	border: var(--mbf-field-border);
	border-radius: var(--mbf-field-radius);
	padding: var(--mbf-field-padding);
	font-family: inherit;
	font-size: inherit;
	line-height: 1.4;
	box-sizing: border-box;
	width: 100%;
	max-width: 100%;
}

/*
 * The select arrow. Without appearance:none a select keeps the platform
 * widget and ignores padding on some platforms; with it, the arrow has to be
 * drawn. An inline SVG data URI keeps it to one request and one colour.
 */
.mbf-form--normalize select {
	-webkit-appearance: none;
	-moz-appearance: none;
	appearance: none;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23888' stroke-width='1.5'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right 0.7em center;
	background-size: 0.7em auto;
	padding-right: 2.2em;
}

.mbf-form--normalize select[multiple] {
	background-image: none;
	padding-right: var(--mbf-field-padding);
}

.mbf-form--normalize textarea {
	min-height: 6em;
	resize: vertical;
}

.mbf-form--normalize input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]):not([type="reset"]):not([type="file"]):not([type="image"]):focus-visible,
.mbf-form--normalize select:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]):not([type="reset"]):not([type="file"]):not([type="image"]):focus-visible,
.mbf-form--normalize textarea:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]):not([type="reset"]):not([type="file"]):not([type="image"]):focus-visible {
	border: var(--mbf-field-border-focus);
	outline: 2px solid var(--mbf-accent);
	outline-offset: 1px;
}

.mbf-form--normalize ::placeholder {
	color: inherit;
	opacity: 0.55;
}

/* Checkbox and radio: alignment only, never a surface. */
.mbf-form--normalize .mbf-field__choice {
	align-items: center;
}

.mbf-form--normalize input[type="checkbox"],
.mbf-form--normalize input[type="radio"] {
	margin: 0;
	flex: 0 0 auto;
}

.mbf-form--normalize .mbf-field__choice-label {
	font-weight: inherit;
	line-height: 1.4;
}

/*
 * Autofill. Chrome paints its own background over the control and ignores
 * background-color; a long inset shadow is the only way to cover it, and the
 * transition delay stops the yellow flashing before the shadow lands.
 */
.mbf-form--normalize input:-webkit-autofill,
.mbf-form--normalize textarea:-webkit-autofill,
.mbf-form--normalize select:-webkit-autofill {
	-webkit-text-fill-color: var(--mbf-field-color);
	-webkit-box-shadow: 0 0 0 100px var(--mbf-field-bg) inset;
	box-shadow: 0 0 0 100px var(--mbf-field-bg) inset;
	transition: background-color 100000s ease-in-out 0s;
}

/* Disabled controls read as unavailable in every mode, not just normalise. */
.mbf-form input:disabled,
.mbf-form select:disabled,
.mbf-form textarea:disabled,
.mbf-form button:disabled {
	cursor: not-allowed;
	opacity: 0.6;
}

/* A label hidden from sight but not from a screen reader.
   Structural, so it holds in "inherit" as well as "normalize". In "off" mode
   no stylesheet loads at all, so the renderer inlines these same declarations
   on the element instead. Never display:none, which would take the label away
   from assistive technology as well as from the eye. */
.mbf-field__label--hidden {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}
