/**
 * form@1.0 — the three-track grid and field chrome.
 * Every row sums to 3/3; below the breakpoint every field is full width.
 */
/* The form is its own container, so the three-track grid and the title answer
   to the WIDTH THEY ARE IN rather than to the viewport. Before this, the only
   collapse rule was a viewport media query, which meant a form in a sidebar on
   a desktop never collapsed: a 1/3 field in a 220px column rendered about 60px
   wide — too narrow for the ZIP code it was labelled for — and the title
   overflowed its column and was clipped mid-word. Found 2026-09-22, the first
   time a form was rendered anywhere but a full-width content section.
   The pattern follows post-loop.css, which already does this.

   `width: 100%` is NOT optional next to `container-type: inline-size`.
   Inline-size containment stops the element sizing itself from its contents,
   so a form that is a flex or grid child with no assigned width collapses to
   nothing: the footer newsletter's label wrapped one word per line, its input
   drew about 50px and the Subscribe button overflowed its own box. That
   regression was introduced and caught in the same pass, 2026-09-22. */
.plexa-form { container-type: inline-size; width: 100%; }
/* THE FIELD FILL is a tint of the content colour over whatever ground the
   form sits on, never a fixed base step. `--color-base-100` is near-black in a
   dark mode, which drew the footer newsletter's input as a black slab on the
   velvet gradient (Rick, 2026-09-22). Content colour contrasts with its own
   ground in every mode, so a small share of it reads as a field on light,
   dark and gradient grounds alike. The share is set by rendering every
   _wip-form-* page (spec 2026-09-25 §1), not by reasoning. */
.plexa-form { --form-fill: color-mix(in oklch, var(--color-base-content) 6%, transparent); }
.plexa-form__form { display: flex; flex-direction: column; gap: var(--space-4, 1rem); }
/* The submit is a button, not a band. A flex column stretches its children,
   which drew "Send" across the full width of the body form and "Subscribe"
   across the footer column (Rick, 2026-09-22). It takes its own width, and
   goes full width only where the CONTAINER is narrow — see the @container
   block at the end of this file. */
.plexa-form__submit { align-self: flex-start; }
/* ONE HEIGHT FOR A FIELD AND ITS BUTTON, 44px (capture research C-F3 / CG3;
   hallmark slop gate 39 "input height = adjacent button height, 44px floor";
   WCAG 2.5.8 target size). The submit measured 38px beside 42px inputs. A
   textarea keeps its own, taller, height. */
.plexa-form__submit { min-height: 2.75rem; height: auto; }
input.form__input:not([type="file"]), select.form__input { min-height: 2.75rem; }
/* `panel: true` (capture research CG2): the form in a card, so its fields,
   button and note read as one unit beside the content that earns it. The card
   is the root (base-100, shadow, radius from the component's classes); the
   inset is a margin on each child rather than padding on the root, because the
   root is the query container: padding would shrink the width the 30rem
   collapse below measures, and a 5-of-12 column (506px at 1248) would lose its
   ZIP-beside-phone row to a card edge. */
.plexa-form--panel { padding-block: 1.5rem; }
.plexa-form--panel > * { margin-inline: 1.5rem; }
/* THE NOTE BESIDE THE BUTTON (skills/forms §8.1, capture research CB11): the
   one reassurance line, on the button's row where there is room and under it
   where there is not. 15px at 80% ink: quieter than a label, never faint. */
.plexa-form__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 1rem; }
.plexa-form__actions > .plexa-form__submit { flex: 0 0 auto; }
.plexa-form__note { flex: 1 1 14rem; margin: 0; font-family: var(--font-body); font-size: 0.9375rem; line-height: 1.45;
  color: color-mix(in oklch, var(--color-base-content) 80%, transparent); }
.form__row { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-4, 1rem); }
.form__field--full { grid-column: span 3; }
.form__field--two-thirds { grid-column: span 2; }
.form__field--third { grid-column: span 1; }
/* Browser review round 1 finding #1 (regression, Task 4's help-above-control,
   site-wide): a row's grid cell stretches every field to the row's height
   (the grid default), but a `.form__field` was plain block flow, so a field
   with `help` (extra text above the control) pushed its own control lower
   than a sibling with none — the control sat wherever the field's own
   content happened to end, not at a shared line. `.form__row`'s three fields
   are grid items so a `.form__field` is already stretched tall enough to
   match its row's tallest sibling; making the field a flex column and giving
   its control (never its label/help, which stay put at the top) `margin-top:
   auto` uses exactly that slack to push the control down to the row's shared
   bottom edge, whatever sits above it.

   `.form__input`/`.form__fieldset`/`.form__option` are the three shapes a
   control takes (render_field(): a plain input/textarea/select, a
   radio/checkboxes fieldset, or a lone checkbox's own label) — see
   class-form-component.php.

   ERROR PARAGRAPHS (checked, not just assumed): `.form__error` is rendered
   AFTER the control, so it is not part of what `margin-top: auto` moves —
   only the control gets pushed down; the error still sits directly under it,
   in normal flow. When a field is showing an error, ITS OWN content grows
   (control + error), which can make it the row's tallest field; a sibling
   with no error is then stretched taller to match and its control's
   `margin-top: auto` follows that extra height down too, so the sibling's
   control no longer lines up with the erroring field's control (which sits
   above its own error, not at the box's bottom) — it lines up with the
   BOTTOM OF THE ERROR instead. That is the one case this rule does not cover
   perfectly; an error is one-shot and per-field, not the steady state a
   visitor sees, so the trade favours the common case (no error) lining up
   exactly.

   PHONE: `.form__row` collapses to one column below, and a lone item in a
   grid track is exactly as tall as its own content — nothing to stretch
   against — so this is a no-op there; the single-column stack is unaffected. */
.form__field { display: flex; flex-direction: column; }
.form__field > .form__input,
.form__field > .form__fieldset,
.form__field > .form__option { margin-top: auto; }
.form__label { display: block; font-family: var(--font-body); font-size: 0.875rem; margin-bottom: 0.25rem; }
/* Required = red *, optional = nothing (Rick, 2026-09-26). */
.form__required { color: var(--color-error); margin-inline-start: 0.15em; font-weight: 600; }
/* The border is derived from the CONTENT colour, not from a fixed base step.
   `--color-base-300` is a light-mode border, so a field on the dark footer
   ground drew a dark edge on a dark fill and the control was barely visible —
   the same class of defect as light ink on a light ground. Content colour
   contrasts with its own ground by definition, in every mode. */
.form__input { width: 100%; font-family: var(--font-body); color: var(--color-base-content);
  background: var(--form-fill);
  border: 1px solid color-mix(in oklch, var(--color-base-content) 32%, transparent);
  border-radius: var(--radius-field, 0.375rem); padding: 0.5rem 0.75rem; }
.form__input:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; }
/* Task 4 (step 13b, spec §6): `help` moved between the label/legend and the
   control, so it now needs its OWN bottom margin to separate it from the
   control that follows — it used to be the field's last child, spaced by
   nothing but its own browser-default paragraph margin. Zeroed inside
   `.form__fieldset`, which already spaces its flex children with `gap`
   (same override pattern as `.form__fieldset .form__label` just below). */
.form__help { margin: 0 0 0.375rem; font-size: 0.8125rem; color: color-mix(in oklch, var(--color-base-content) 60%, transparent); }
.form-divider { border: 0; border-top: 1px solid var(--color-base-300); margin: var(--space-6, 1.5rem) 0; }
.form__group { border: 0; padding: 0; margin: 0; display: flex; flex-direction: column; gap: var(--space-4, 1rem); }
.form__group-label { font-family: var(--font-body); font-size: 0.9375rem; font-weight: 600; color: var(--color-base-content); padding: 0; margin: 0; }
.form__repeater { display: flex; flex-direction: column; gap: var(--space-4, 1rem); }
.form__repeater-item { display: flex; flex-direction: column; gap: var(--space-3, 0.75rem);
  padding: var(--space-4, 1rem); border: 1px solid color-mix(in oklch, var(--color-base-content) 32%, transparent); border-radius: var(--radius-box, 0.5rem); }
.form__repeater-remove { align-self: flex-start; }
/* The add button is a button, not a band. Same defect class as the submit
   (Rick, 2026-09-22): `.form__repeater` is a flex column, which stretches its
   children, so "Add attendee"/"Add note" drew as a full-width thin bar with
   small centred text instead of a natural-width button. It takes its own
   width, and goes full width only where the CONTAINER is narrow — see the
   @container block below. Found 2026-09-25, form-containers.png / form-optional-mobile.png. */
.form__repeater-add { align-self: flex-start; }
.form__repeater-remove:disabled, .form__repeater-add:disabled { opacity: 0.5; cursor: not-allowed; }
.form__repeater-template { display: none; }
[data-visible-when][hidden] { display: none; }
.form__fieldset { border: 0; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 0.375rem; }
.form__fieldset .form__label { margin-bottom: 0.25rem; padding: 0; }
.form__fieldset .form__help { margin-bottom: 0; }
.form__option { display: flex; align-items: center; gap: 0.5rem; font-family: var(--font-body); font-size: 0.875rem; font-weight: normal; }
.form__option input { width: auto; }

/* form@1.0 Task 9 — the honeypot. Off-screen, never display:none (some bots
   specifically skip a display:none field, so this still occupies layout,
   just outside the viewport). */
.form__hp { position: absolute; left: -9999px; top: auto; width: 1px; height: 1px; overflow: hidden; }

/* Task 9 — one-shot validation errors, re-rendered after a failed submission. */
.form__error { font-size: 0.8125rem; color: var(--color-error); margin: 0.25rem 0 0; }
.form__error--general { font-size: 0.9375rem; padding: var(--space-3, 0.75rem) var(--space-4, 1rem);
  border: 1px solid var(--color-error); border-radius: var(--radius-box, 0.5rem); margin: 0; }
[aria-invalid="true"] { border-color: var(--color-error); }

/* Task 11 — success.message, the no-redirect case's own one-shot banner. */
.form__success { font-size: 0.9375rem; padding: var(--space-3, 0.75rem) var(--space-4, 1rem);
  border: 1px solid var(--color-success); border-radius: var(--radius-box, 0.5rem); margin: 0; }

/* NATIVE CONTROLS. Text inputs carried the design system from the start and
   checkbox, radio, file and select did not — they rendered as raw browser
   defaults on a themed page, which is the single most visible thing in the
   "every field type" capture. Sized in `em` so each one tracks the label it
   sits beside, and coloured only through tokens. */
.form__option input[type="checkbox"], .form__option input[type="radio"] {
  appearance: none; -webkit-appearance: none;
  width: 1.125em; height: 1.125em; flex: 0 0 auto; margin: 0;
  border: 1px solid color-mix(in oklch, var(--color-base-content) 32%, transparent); background: var(--form-fill);
  display: grid; place-content: center; cursor: pointer;
}
.form__option input[type="checkbox"] { border-radius: calc(var(--radius-field, 0.375rem) * 0.6); }
.form__option input[type="radio"] { border-radius: 50%; }
.form__option input[type="checkbox"]::before,
.form__option input[type="radio"]::before {
  content: ""; width: 0.625em; height: 0.625em; transform: scale(0);
  transition: transform 120ms ease-in-out; background: var(--color-primary-content, var(--color-base-100));
}
.form__option input[type="checkbox"]::before {
  clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%);
}
.form__option input[type="radio"]::before { border-radius: 50%; }
.form__option input[type="checkbox"]:checked, .form__option input[type="radio"]:checked {
  background: var(--color-primary); border-color: var(--color-primary);
}
.form__option input[type="checkbox"]:checked::before,
.form__option input[type="radio"]:checked::before { transform: scale(1); }
.form__option input[type="checkbox"]:focus-visible,
.form__option input[type="radio"]:focus-visible {
  outline: 2px solid var(--color-primary); outline-offset: 2px;
}

/* The select keeps its own chevron rather than the operating system's, so a
   Mac, a PC and a phone draw the same control. */
select.form__input {
  appearance: none; -webkit-appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: right 1.05rem top 55%, right 0.75rem top 55%;
  background-size: 0.3rem 0.3rem, 0.3rem 0.3rem;
  background-repeat: no-repeat;
  padding-right: 2rem;
}

/* The file control's own button, rather than the browser's grey slab. */
.form__input[type="file"] { padding: 0.375rem 0.5rem; }
.form__input[type="file"]::file-selector-button {
  font-family: var(--font-body); font-size: 0.875rem;
  margin-right: 0.75rem; padding: 0.3rem 0.75rem; cursor: pointer;
  color: var(--color-base-content); background: color-mix(in oklch, var(--color-base-content) 12%, transparent);
  border: 1px solid color-mix(in oklch, var(--color-base-content) 32%, transparent); border-radius: var(--radius-field, 0.375rem);
}

/* REPEATER BUTTONS. `btn` with no variant resolved to near-white on white:
   "Add attendee" read as empty space and the disabled "Remove" was illegible.
   An outline gives them a boundary without competing with the submit. */
.form__repeater-add, .form__repeater-remove {
  border: 1px solid color-mix(in oklch, var(--color-base-content) 32%, transparent);
  border-radius: var(--radius-field, 0.375rem);
  background: var(--form-fill); color: var(--color-base-content);
}
.form__repeater-add:hover:not(:disabled), .form__repeater-remove:hover:not(:disabled) {
  border-color: var(--color-primary);
}
.form__repeater-remove:disabled, .form__repeater-add:disabled { opacity: 0.45; }

/* Narrow CONTAINER, not narrow viewport — see the note at the top. A form in a
   sidebar gets the same one-column treatment a phone gets, because the reason
   is the same: three tracks do not fit. */
@container (max-width: 30rem) {
  .form__row { grid-template-columns: 1fr; }
  .form__field--full, .form__field--two-thirds, .form__field--third { grid-column: span 1; }
  .plexa-form__title { font-size: clamp(1.25rem, 9cqi, 1.75rem); line-height: 1.15; }
  .plexa-form__submit { align-self: stretch; }
  .plexa-form__actions { flex-direction: column; align-items: stretch; }
  /* The note's 14rem basis is a WIDTH beside the button; in this column it
     became a 224px HEIGHT under two lines of text (footer review round 1, #7:
     ~200px of empty band under the newsletter on a phone). */
  .plexa-form__note { flex-basis: auto; }
  .form__repeater-add { align-self: stretch; }
}

/* ONE FIELD, ONE LINE (capture research CG9; hallmark C2 "inline form as
   CTA"): a form that asks one thing (a newsletter's email) sets its button on
   the field's baseline once the container has room, and the note on the line
   under both. Under 30rem it stacks like every other form. */
@container (min-width: 30rem) {
  .plexa-form--single .plexa-form__form { flex-direction: row; flex-wrap: wrap; align-items: flex-end; }
  .plexa-form--single .form__row { flex: 1 1 16rem; }
  .plexa-form--single .plexa-form__actions { display: contents; }
  .plexa-form--single .plexa-form__submit { align-self: flex-end; }
  .plexa-form--single .plexa-form__note { flex: 1 0 100%; }
}

/* A FORM TITLE IS NOT A PAGE TITLE. The element is an <h2>, so with no rule of
   its own it inherited the page display scale — on the `dramatic` type scale
   that drew "Talk to us" at roughly 80px, louder than the section heading above
   it and louder than the page's own title band. A form is a control, and its
   label sits with the fields it introduces rather than competing with the page.
   Capped here rather than in the component so the size stays a design decision
   in CSS. Rick, 2026-09-22: "the titles are very poor". */
.plexa-form__title {
  font-size: clamp(1.25rem, 2.2cqi + 1rem, 1.875rem);
  line-height: 1.2;
  margin: 0 0 var(--space-2, 0.5rem);
  overflow-wrap: anywhere;
}

@media (max-width: 767px) {
  .form__row { grid-template-columns: 1fr; }
  .form__field--full, .form__field--two-thirds, .form__field--third { grid-column: span 1; }
}
