/**
 * @file
 * The "Add an event" page — the node form as Drupal actually renders it.
 *
 * WHY THIS FILE EXISTS
 * ====================
 * css/components/form.css was written against the markup a Webform emits:
 *
 *   fieldset > legend + .fieldset-wrapper > .form-item > label + input
 *
 * /add is not a Webform. It is the `event_registration` NODE form, altered by
 * the add_event module, and Drupal builds a node form out of quite different
 * parts:
 *
 *   form.node-form
 *     .layout-region.layout-region-node-main
 *       .layout-region__content
 *         .field--type-string.js-form-wrapper.form-wrapper      one per field
 *           .js-form-item.form-item.js-form-type-textfield      the control
 *     .layout-region.layout-region-node-secondary   "advanced" (editors only)
 *     .layout-region.layout-region-node-footer      the actions
 *
 * Two consequences, and between them they are the whole bug report:
 *
 * 1. THE THREE REGION WRAPPERS COME FROM CORE, and Claro is what normally
 *    styles them. A front-end theme is handed the markup and none of the CSS,
 *    and every `.node-form > …` child selector in form.css misses by two
 *    levels — so the spacing, the panels and the section rhythm all silently
 *    did nothing on this one page.
 *
 * 2. DRUPAL'S CHECKBOX AND RADIO ITEMS ARE NOT `.form-check`. They are
 *    `.js-form-type-checkbox` / `.js-form-type-radio`, so the rule that puts a
 *    tick box and its label on one line never matched: all sixteen genres, the
 *    seven days and every yes/no pair rendered as a box with an UPPERCASE
 *    label underneath it, because the label fell through to the generic
 *    `label` style. That is what "fields are not sitting correctly" looks like.
 *
 * WHAT THIS FILE DOES NOT DO
 * ==========================
 * Nothing here is scoped to a field name or an `#edit-…` id. The outgoing
 * theme had six hundred lines of those and they broke every time a field was
 * renamed; these rules key off what Drupal's Form API guarantees — the element
 * type classes — so a new field on the content type is styled the day it is
 * added, with no CSS change at all.
 */

/* ---------------------------------------------------------------------------
 * 1. The three regions core wraps a node form in
 * ------------------------------------------------------------------------ */

/**
 * Stacked, full width, and each able to shrink.
 *
 * Claro makes these a two-column grid at 61rem, with the "advanced" sidebar
 * beside the fields. This form lives inside a 60rem measure inside the page
 * container, so there is no room for a sidebar and no reason for one: the
 * advanced group is editor-only, and an editor reading it wants it under the
 * fields, not squeezed beside them.
 */
.node-form .layout-region {
  display: block;
  inline-size: 100%;
  min-inline-size: 0;
}

.node-form .layout-region__content {
  min-inline-size: 0;
}

/* An empty region — the usual case for `secondary`, which is entirely
   permission-gated — takes no space. Without this the form ended in a
   mysterious band of nothing above the Submit button. */
.node-form .layout-region:not(:has(input, select, textarea, details, .form-item)) {
  display: none;
}

/* ---------------------------------------------------------------------------
 * 2. TWO COLUMNS AT THE HEADER'S WIDTH
 *
 * The form used to be a single 60rem column — a measure borrowed from running
 * text, and wrong for a form of thirty fields. Read on a laptop it was two full
 * screens of scrolling with a third of the window empty either side, and it did
 * not line up with anything else on the page.
 *
 * It is now the page container's width — the same edges as the header, the
 * cards and the newsletter — with the fields in two columns. Short fields (a
 * title, a date, a phone number) take half a row; the ones that genuinely need
 * the width (the picture, the description, sixteen genre checkboxes) take the
 * whole of it.
 *
 * WHICH FIELDS SPAN IS DECIDED BY WIDGET, NOT BY NAME — with one exception,
 * `.field--name-title`, and it is a safe one: `title` is a base field that
 * every node type has and no site builder can rename. The event's name is the
 * first thing on the form and the longest single line on it, so it takes the
 * row; without it the form opened with a field and an empty half beside it.
 *
 * Otherwise: `.field--type-image`,
 * `.field--type-text-with-summary`, a checkbox set — those are facts about the
 * kind of control Drupal built, so a field added to the content type next year
 * lands in the right place with no CSS change. Naming `field_article_image`
 * here would be the beginning of the six hundred lines of id-scoped rules the
 * outgoing theme died of.
 *
 * Source order is left-to-right, row by row, so the tab order is what the eye
 * follows — the thing two-column forms usually get wrong.
 * ------------------------------------------------------------------------ */

/**
 * EVERY CONTAINER OF FIELDS IS THE SAME GRID.
 *
 * The first version of this rule was written against `.layout-region__content`
 * alone, and on the live site it did almost nothing: that form uses Field
 * Group, so the fields are not children of the region — they are children of
 * "Event location", "Event time" and the other section wrappers. The two-column
 * grid was being applied to a list of five sections, each of which then laid
 * its own fields out full width. That is the "now too wide" screenshot.
 *
 * So the grid is declared for every box that can hold fields: the region, a
 * fieldset's wrapper, a details' wrapper, and Field Group's own wrapper. A form
 * with no groups gets two columns; a form with five gets two columns inside
 * each of them; and nothing has to know which of those it is.
 */
.node-form :is(
  .layout-region__content,
  .fieldset-wrapper,
  .details-wrapper,
  .field-group-format-wrapper
) {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-l);
  align-items: start;
}

/**
 * A GROUP WITH NO INNER WRAPPER IS ITSELF THE GRID.
 *
 * Field Group renders differently per formatter: a fieldset gets a
 * `.fieldset-wrapper` around its fields, `details` gets a `.details-wrapper`,
 * and the plain-div formatters put the fields straight inside the group. The
 * list above covers the first two; this covers the third, without ever
 * double-applying to a group that does have a wrapper.
 */
.node-form :is([id^="edit-group-"], [data-drupal-selector^="edit-group-"]):not(
  :has(> :is(.fieldset-wrapper, .details-wrapper, .field-group-format-wrapper))
) {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-l);
  align-items: start;
}

@media (min-width: 62rem) {
  .node-form :is([id^="edit-group-"], [data-drupal-selector^="edit-group-"]):not(
    :has(> :is(.fieldset-wrapper, .details-wrapper, .field-group-format-wrapper))
  ) {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-l) var(--space-xl);
  }
}

/* A composite WIDGET's wrapper is not a container of fields — it is one field,
   with a date and a time in it, or sixteen checkboxes. It keeps its own
   layout. */
.node-form .field--type-datetime .fieldset-wrapper,
.node-form .field--widget-options-buttons .fieldset-wrapper,
.node-form .fieldset-wrapper:has(> .form-checkboxes),
.node-form .fieldset-wrapper:has(> .form-radios),
.node-form .fieldset-wrapper:has(> .container-inline) {
  display: block;
}

@media (min-width: 62rem) {
  .node-form :is(
    .layout-region__content,
    .fieldset-wrapper,
    .details-wrapper,
    .field-group-format-wrapper
  ) {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-l) var(--space-xl);

  }

  /**
   * The full-width row: anything that is a picture, a body of text, or a set
   * of options long enough to want the room.
   */
  .node-form :is(
    .layout-region__content,
    .fieldset-wrapper,
    .details-wrapper,
    .field-group-format-wrapper
  ) > :is(
    .field--name-title,
    .field--type-image,
    .field--type-file,
    .field--type-text-with-summary,
    .field--type-text-long,
    .field--type-string-long,
    .field--widget-string-textarea,
    .field--widget-options-buttons:has(.form-checkboxes),
    .field--widget-entity-reference-autocomplete-tags,
    .field--type-geolocation,
    .field--type-geofield,
    fieldset,
    details,
    [class*="field-group-"],
    [id^="edit-group-"],
    [data-drupal-selector^="edit-group-"]
  ) {
    grid-column: 1 / -1;
  }

  /**
   * A `#type => item` is a label and a description with no control under it —
   * on this form, the "Map" heading above the picker. It is explanatory text,
   * so it takes the row rather than sitting in a column beside a field it is
   * not about.
   */
  .node-form :is(
    .layout-region__content,
    .fieldset-wrapper,
    .details-wrapper,
    .field-group-format-wrapper
  ) > :is(.js-form-type-item, .form-type-item, .add-event-map) {
    grid-column: 1 / -1;
  }

  /* A radio set is two or three options on one line: it does not need the row.
     Stated after the rule above because `:has(.form-checkboxes)` and this one
     can both match a widget that renders both. */
  .node-form .layout-region__content > .field--widget-options-buttons:has(.form-radios),
  .node-form .fieldset-wrapper > .field--widget-options-buttons:has(.form-radios) {
    grid-column: auto;
  }
}

/**
 * THE CONTROL IS CAPPED, NOT THE GRID.
 *
 * The cap used to be on the field grid — 63rem, two 30rem columns and the gap.
 * That was right when the whole form was one card: the card was the container's
 * width and the fields sat in a 63rem measure inside it.
 *
 * Now the SECTION is the card, and a capped grid left every card 300px empty on
 * its right-hand side — six boxes with a bite out of each. So the grid fills
 * its card (the card's edge is the alignment that matters, and it is the
 * header's edge) and the cap is where the reason for it always was: on the
 * control. A 590px box for a phone number is not a form, it is a spreadsheet.
 *
 * Text that is genuinely long — a summary, a description, a body — gets the
 * wider measure, because those are read as prose while being written.
 */
.node-form .form-item :is(input, select):not([type="checkbox"]):not([type="radio"]):not([type="file"]) {
  max-inline-size: 34rem;
}

.node-form .form-item textarea,
.node-form .text-format-wrapper,
.node-form .ck-editor,
/* `.ck.ck-editor` — two classes — on purpose: the containment block further
   down this file caps every control at `100%` of its container, and at equal
   specificity the later rule was winning, so the rich-text editor alone ran the
   full width of the card while every other control kept its measure. */
.node-form .ck.ck-editor {
  max-inline-size: min(100%, 60rem);
}

/**
 * THE WHOLE FIELD TAKES THAT MEASURE, NOT JUST THE WRITING SURFACE.
 *
 * The cap above is on the editor and on `.text-format-wrapper`. CKEditor's
 * character readout is rendered OUTSIDE both of them — it is a sibling of the
 * wrapper inside the field — so it kept the card's full width while the box
 * it describes stopped at 60rem. On a wide screen the counter ran about 260px
 * past the right-hand edge of the editor, which reads as a misaligned box
 * rather than as a caption belonging to it.
 *
 * Capping the field itself lines up the label, the editor, the counter and
 * the note on the same two edges, and does it wherever Drupal chooses to put
 * the counter — which is the part that is not safe to assume.
 *
 * EVERY SELECTOR HERE CARRIES THREE CLASSES, AND THAT IS NOT DECORATION.
 * The containment block further down this file caps everything matching
 * `.form-wrapper, .js-form-wrapper, .form-item, …` at `100%`, with two
 * classes. A two-class selector here loses to it on source order — measured:
 * the counter stayed at the container's full width and only the shape where
 * `:has()` happened to add a third class was fixed. `:has()` takes the
 * specificity of its argument, so the first two reach 0,3,0 on their own; the
 * third names the widget type as well as the wrapper to get there. This is
 * the same trap the `.ck.ck-editor` note above describes.
 *
 * Two shapes because Drupal puts the counter in one of two places depending
 * on the widget: inside the form item next to the editor, or beside the form
 * item inside the field wrapper. Both are covered, so it does not matter
 * which one this site produces.
 */
.node-form .form-item:has(> .text-format-wrapper),
.node-form .js-form-item:has(> .text-format-wrapper),
.node-form :is(.field--type-text-with-summary, .field--type-text-long).js-form-wrapper {
  max-inline-size: min(100%, 60rem);
}

/**
 * At the cap, the editor is full.
 *
 * js/editor-limit.js in add_event sets this when the Description reaches
 * ADD_EVENT_BODY_MAX and the editor stops taking new characters. Without a
 * mark, a box that silently ignores typing reads as broken rather than full.
 * The border is the signal; the sentence under the field carries the detail.
 */
.node-form .is-editor-full .ck.ck-editor {
  border-color: var(--me-magenta);
}

/**
 * A field's own box can never be wider than the column it sits in.
 *
 * `.form-item` is `display: grid` with one implicit `auto` track, and an auto
 * track takes its minimum from the CONTENT — so a control with a large
 * intrinsic width pushes the track past the container instead of shrinking.
 * `<input type="file">` is exactly that control: on a phone the image field's
 * label, its widget and its description all measured 339px inside a 289px
 * column and hung off the right-hand edge of the card. Flooring the track at 0
 * is the same fix the newsletter card needed, for the same reason.
 */
.node-form .form-item {
  grid-template-columns: minmax(0, 1fr);
}

.node-form input[type="file"] {
  max-inline-size: 100%;
  min-inline-size: 0;
}

/* The control inside a field wrapper owns no outer margin — the grid's gap is
   the spacing, and a margin on top of it spaces one field twice. */
.node-form .layout-region__content > * > .form-item,
.node-form .layout-region__content > * > .form-item:last-child,
.node-form .layout-region__content > .form-item {
  margin-block-end: 0;
}

/* ---------------------------------------------------------------------------
 * 3. Checkboxes and radios — Drupal's real class names
 *
 * The same treatment `.form-check` gets in form.css. Listed separately rather
 * than merged into that file so the two markup dialects stay legible: that one
 * is the Webform's, this one is the Form API's.
 * ------------------------------------------------------------------------ */

/**
 * Scoped to `.node-form`, and that is not decoration — it is what wins.
 *
 * form.css carries `.js-form-type-checkboxes > div { display: grid }`, written
 * for the Webform dialect where that child div is the CONTAINER of the options.
 * In the Form API's dialect the same selector lands on each individual option
 * instead, which is precisely what stacked every label under its tick box: a
 * one-column grid, at (0,1,1), beating a bare `.js-form-type-checkbox` at
 * (0,1,0). Adding `.node-form` takes this to (0,2,0) and settles it, without
 * touching the rule that is still correct for the other markup.
 */
.node-form .js-form-type-checkbox,
.node-form .js-form-type-radio,
.node-form .form-type-checkbox,
.node-form .form-type-radio {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2xs);
  margin-block-end: var(--space-2xs);
}

/**
 * The label beside the box, in sentence case.
 *
 * `.option` is the class Drupal puts on a checkbox's or radio's label, and it
 * is the one that has to beat the uppercase `label` rule — hence naming both
 * the item and the label rather than relying on inheritance.
 */
.node-form .js-form-type-checkbox > label,
.node-form .js-form-type-radio > label,
.node-form .form-type-checkbox > label,
.node-form .form-type-radio > label,
.node-form label.option {
  font-size: var(--step--1);
  font-weight: var(--weight-medium);
  letter-spacing: normal;
  text-transform: none;
  color: var(--text-primary);
  cursor: pointer;
}

/**
 * The set of them: a responsive column layout rather than one long list.
 *
 * Sixteen genres in a single column is 600px of scrolling past the fields that
 * follow it — the complaint the old site's form got most often.
 */
.node-form .form-checkboxes,
.node-form .form-radios,
.node-form .js-form-type-checkboxes,
.node-form .js-form-type-radios,
.node-form .js-form-type-checkboxes > div.form-checkboxes,
.node-form .js-form-type-radios > div.form-radios {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(16rem, 100%), 1fr));
  gap: var(--space-2xs) var(--space-m);
  align-items: start;
}

/* Two or three yes/no options do not want a 14rem column each. */
.node-form .form-radios {
  grid-template-columns: repeat(auto-fit, minmax(min(8rem, 100%), auto));
  justify-content: start;
  gap: var(--space-3xs) var(--space-l);
}

/* ---------------------------------------------------------------------------
 * 4. Composite widgets: a label, not a panel
 *
 * A date field, a checkbox set and a radio set each arrive as
 * `fieldset.fieldgroup > legend + .fieldset-wrapper`, and form.css gives every
 * `.fieldset-wrapper` the theme's panel — border, background, 32px of padding.
 * That is right for a Webform, where a fieldset groups eight related fields.
 * Here it wraps ONE field, so the form came out as a stack of bordered boxes
 * with the plain text fields loose between them: the same field, two different
 * shapes, depending on which widget Drupal happened to use.
 *
 * Inside a node form the panel comes off and the legend becomes the field's
 * label, so a date reads exactly like a title.
 * ------------------------------------------------------------------------ */

.node-form fieldset {
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
}

.node-form .fieldset-wrapper {
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
}

/* The legend, styled as the field label it actually is — same size, same case,
   same colour as a `<label>`; see the typography block at the end of the file. */
.node-form legend,
.node-form .fieldset-legend {
  display: block;
  inline-size: 100%;
  margin: 0 0 var(--space-3xs);
  padding: 0;
}

/* ---------------------------------------------------------------------------
 * 5. Date and time
 * ------------------------------------------------------------------------ */

/**
 * The pair side by side, each with its own label above it.
 *
 * `.container-inline` is Drupal's "put these on one line" wrapper and its own
 * stylesheet floats the children, which dropped the two labels to the left of
 * their inputs and left the baselines two pixels apart. A flex row with the
 * items back in column direction is the same intent, correctly.
 */
.node-form .container-inline {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xs) var(--space-s);
  align-items: end;
}

.node-form .container-inline > .form-item {
  display: grid;
  gap: var(--space-3xs);
  margin-block-end: 0;
  min-inline-size: 0;
}

.node-form .container-inline label {
  display: block;
  float: none;
}

.node-form .container-inline input {
  inline-size: auto;
  min-inline-size: 9rem;
}

/* ---------------------------------------------------------------------------
 * 6. Descriptions, and the text-format furniture under a rich text field
 * ------------------------------------------------------------------------ */

/**
 * A description is a caption under its control, not a box.
 *
 * form.css puts a panel round `.text-format-wrapper .description` — which is
 * right when the description is the only thing in a Webform's markup area, and
 * wrong here, where every field has one and the page turned into a ladder of
 * empty bordered strips.
 */
.node-form .description,
.node-form .form-item__description,
.node-form .text-format-wrapper .description {
  margin-block-start: var(--space-3xs);
  padding: 0;
  border: 0;
  background: none;
  color: var(--text-muted);
  font-size: var(--step--2);
  line-height: var(--leading-normal);
}

/**
 * "Text format: Basic HTML / About text formats".
 *
 * Drupal's chrome, not the council's content. It is required to stay in the
 * DOM — the select is a real form control and removing it changes what the
 * form submits — so it is made quiet rather than hidden: no panel, small type,
 * and the two controls on one line at the foot of the editor.
 */
.node-form .filter-wrapper {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2xs) var(--space-s);
  margin-block-start: var(--space-2xs);
  padding: 0;
  border: 0;
  background: none;
}

.node-form .filter-wrapper .form-item {
  display: flex;
  align-items: center;
  gap: var(--space-2xs);
  margin: 0;
}

.node-form .filter-wrapper select {
  inline-size: auto;
  min-inline-size: 10rem;
  padding-block: 0.25rem;
  min-block-size: 0;
  font-size: var(--step--2);
}

.node-form .filter-wrapper .filter-help a,
.node-form .filter-wrapper .filter-guidelines {
  font-size: var(--step--2);
  color: var(--text-muted);
}

/* ---------------------------------------------------------------------------
 * 7. The image widget
 * ------------------------------------------------------------------------ */

.node-form .image-widget,
.node-form .form-managed-file {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2xs) var(--space-s);
  padding: var(--space-s);
  border: 1px dashed var(--border-strong);
  border-radius: var(--card-radius);
  background: var(--surface-1);
}

.node-form .image-widget-data {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2xs) var(--space-s);
  margin: 0;
  min-inline-size: 0;
}

.node-form .image-preview {
  margin: 0;
}

/* The upload button is secondary to the file picker beside it: the visitor
   chooses a file first, and only then has anything to upload. */
.node-form .form-managed-file .form-submit {
  margin: 0;
}

/* ---------------------------------------------------------------------------
 * 8. The "advanced" group — editors only
 * ------------------------------------------------------------------------ */

/**
 * Vertical tabs without the vertical tabs.
 *
 * Core's vertical-tabs JavaScript is an admin-theme library; in a front-end
 * theme the panes render as a plain stack of `<details>`. Rather than fight
 * that, the stack is given a top rule and the details are styled as ordinary
 * disclosures, so an editor sees a tidy list of optional sections after the
 * fields rather than a run of unstyled summaries.
 */
.node-form .layout-region-node-secondary {
  margin-block-start: var(--space-xl);
  padding-block-start: var(--space-l);
  border-block-start: 1px solid var(--border-subtle);
}

.node-form .vertical-tabs,
.node-form .vertical-tabs__panes {
  display: block;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
}

.node-form .layout-region-node-secondary details {
  margin-block-end: var(--space-2xs);
  padding: var(--space-2xs) var(--space-s);
  border: 1px solid var(--border-subtle);
  border-radius: var(--card-radius);
  background: var(--surface-1);
}

.node-form .layout-region-node-secondary summary {
  color: var(--text-secondary);
  font-size: var(--step--1);
  font-weight: var(--weight-bold);
  cursor: pointer;
}

.node-form .layout-region-node-secondary .details-wrapper {
  padding-block-start: var(--space-2xs);
}

/* The vertical tabs menu, if the admin JS ever does run here: it lists the
   same panes a second time. */
.node-form .vertical-tabs__menu {
  display: none;
}

/* ---------------------------------------------------------------------------
 * 9. The actions
 * ------------------------------------------------------------------------ */

.node-form .layout-region-node-footer {
  margin-block-start: var(--space-l);
}

/**
 * Buttons on one row, primary first, wrapping on a phone.
 *
 * `.form-actions` already has its panel from form.css; this is only the
 * arrangement inside it. `input[type="submit"]` is named as well as `.button`
 * because a node form's actions are inputs, not `<button>`s, and the theme's
 * button skin is applied to them by name.
 */
.node-form .form-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-2xs) var(--space-s);
}

.node-form .form-actions .form-submit {
  margin: 0;
}

/* Drupal's own "Preview" is a secondary action; only Submit is primary. */
.node-form .form-actions .form-submit:not(.button--primary):not([value="Submit"]) {
  background: transparent;
  border-color: var(--border-strong);
  color: var(--text-secondary);
  box-shadow: none;
}

.node-form
  .form-actions
  .form-submit:not(.button--primary):not([value="Submit"]):hover {
  border-color: var(--me-magenta);
  color: var(--text-primary);
}

/* ---------------------------------------------------------------------------
 * 10. Errors
 * ------------------------------------------------------------------------ */

/**
 * The add_event module validates a dozen fields and marks each one with
 * Drupal's `.error` class. The theme styles `.form-item--error`, which is
 * Claro's name for the same state; both are named here so an invalid field is
 * visibly invalid on this page too.
 */
.node-form :is(input, select, textarea).error {
  border-color: var(--me-danger, #ff6b6b);
  background: color-mix(in srgb, var(--me-danger, #ff6b6b) 8%, var(--input-bg));
}

.node-form :is(input, select, textarea).error:focus {
  outline-color: var(--me-danger, #ff6b6b);
}

/* ---------------------------------------------------------------------------
 * 11. TYPE SIZES — the other half of the complaint
 *
 * The theme's form labels are `--step--2`: about 11.8px, uppercase, in the
 * secondary text colour. That is a MICRO-LABEL, and it is right where it came
 * from — the caption over a card's date, the "WHEN" above a panel, a legend on
 * a filter — small text that names a value the visitor is already looking at.
 *
 * It is the wrong instrument for a form. Here the label is not a caption on
 * something visible; it is the ONLY statement of what the empty box below it
 * wants, it is read before the visitor has any context, and there are thirty of
 * them. At 11.8px uppercase, "EMAIL AND/OR PHONE NUMBER" is a puzzle.
 *
 * So on this page:
 *   label / legend      11.8px UPPERCASE  ->  14.7px sentence case, primary
 *   input, select       14.7px            ->  16-18px (the body size)
 *   description         11.8px            ->  14.7px
 *   option label        14.7px            ->  16-18px
 *
 * Sentence case as well as bigger: uppercase removes the word shapes that make
 * a phrase readable at a glance, which costs most on the longest labels — the
 * ones on this form. The pink uppercase micro-label is not gone from the page,
 * it is just used for what it is good at: the eyebrow on the intro card.
 * ------------------------------------------------------------------------ */

.node-form label,
.node-form legend,
.node-form .fieldset-legend {
  color: var(--text-primary);
  font-size: var(--step-0);
  font-weight: var(--weight-bold);
  letter-spacing: normal;
  text-transform: none;
  line-height: var(--leading-snug);
}

/**
 * A SECTION HEADING IS NOT A FIELD LABEL.
 *
 * "Event location", "Event time", "Your details" — the Field Group sections —
 * were coming out at the same size and weight as "Venue name" inside them, so
 * the form read as one flat list of thirty labels with no hierarchy at all.
 *
 * A section is a fieldset, a details or a Field Group wrapper that is a direct
 * child of the region — as opposed to the fieldset a date widget builds around
 * ONE field, which is a label and is styled as one above.
 */
/**
 * EACH SECTION IS ITS OWN BLOCK — AND WHERE THE LAST THREE PASSES WENT WRONG.
 *
 * This file was written against the node form Claro renders:
 *
 *   form.node-form > .layout-region-node-main > .layout-region__content > …
 *
 * That structure does not exist here. `node-edit-form.html.twig` — the
 * template that produces those region wrappers — lives in CLARO, not in core,
 * so a front-end theme is handed the plain `form` theme hook and the form's
 * direct children are the Field Group fieldsets themselves:
 *
 *   form.node-form
 *     fieldset#edit-group-event-detail
 *       legend > span.fieldset__legend-text        "Event details"
 *       div.fieldset-wrapper                       the fields
 *     fieldset#edit-group-time-                    …and six more
 *     div#edit-field-latitude-wrapper              a stray, hidden input only
 *     div.captcha                                  a stray with a real field
 *     div.form-actions
 *
 * Every `.layout-region__content > …` selector below therefore matched
 * NOTHING on the live site, which is why three rounds of section styling
 * looked right in the preview and changed nothing on the page. The preview
 * fixture is now built from the live markup, ids and all.
 *
 * A SECTION is a fieldset that is a direct child of the form — or of the
 * `.form-section` wrapper the theme's form_alter adds, for the Field Group
 * formatters that render something other than a fieldset. Its `.fieldset-wrapper`
 * is the card; that is the div form.css already treats as the panel, and rule 4
 * below takes the panel off every fieldset in the form to stop each date and
 * checkbox widget becoming a box of its own. This puts it back where it belongs.
 */
.node-form > fieldset,
.node-form > .form-section,
.node-form .layout-region__content > fieldset {
  margin: 0 0 var(--space-l);
  padding: var(--space-l);
  border: 1px solid var(--border-subtle);
  border-radius: var(--card-radius);
  background: var(--surface-1);
}

@media (min-width: 62rem) {
  .node-form > fieldset,
  .node-form > .form-section,
  .node-form .layout-region__content > fieldset {
    padding: var(--space-xl);
  }
}

/* The wrapper inside a section card is the field grid and nothing else — the
   card is the fieldset's now, and form.css's panel on `.fieldset-wrapper` would
   draw a second one just inside the first. */
.node-form > fieldset > .fieldset-wrapper,
.node-form > .form-section > * > .fieldset-wrapper,
.node-form .layout-region__content > fieldset > .fieldset-wrapper {
  clear: both;
  padding: 0;
  border: 0;
  background: none;
}

/**
 * THE SECTION HEADING, INSIDE THE CARD.
 *
 * Two things were wrong with it. First the class: the legend's inner span is
 * `.fieldset__legend-text` — this theme's own fieldset template writes it — and
 * these rules were looking for Drupal's `.fieldset-legend`, which this page
 * never emits. That one wrong name is why "Event details" kept coming out at
 * field-label size: it fell through to the composite-widget label style meant
 * for "Genre" and "Start".
 *
 * Second the box. A `<legend>` is laid out in the fieldset's BORDER area, so
 * with padding on the fieldset the heading would sit astride the card's top
 * edge. Floating it takes it out of that special rendering and makes it an
 * ordinary block inside the padding box; `.fieldset-wrapper` clears the float,
 * which is what keeps the fields from wrapping around it — the failure that
 * made an earlier build put the panel on the wrapper instead.
 */
.node-form > fieldset > legend,
.node-form > .form-section > * > legend,
.node-form > .form-section > * > :is(h2, h3, h4, .field-group-format-title),
.node-form .layout-region__content > fieldset > legend {
  float: left;
  display: block;
  inline-size: 100%;
  margin: 0 0 var(--space-m);
  padding: 0;
  color: var(--text-primary);
}

.node-form > fieldset > legend > :is(.fieldset__legend-text, .fieldset-legend),
.node-form > .form-section > * > legend > :is(.fieldset__legend-text, .fieldset-legend),
.node-form > .form-section > * > :is(h2, h3, h4, .field-group-format-title),
.node-form .layout-region__content > fieldset > legend > :is(.fieldset__legend-text, .fieldset-legend) {
  display: inline-block;
  margin: 0;
  padding: 0 0 var(--space-3xs);
  border-block-end: 2px solid var(--me-magenta);
  color: var(--text-primary);
  font-size: var(--step-2);
  font-weight: var(--weight-black);
  letter-spacing: var(--tracking-tight);
  line-height: var(--leading-snug);
  text-transform: none;
}

/* A section's own description sits under its heading, not beside a field. */
.node-form > fieldset > .fieldset-wrapper > .fieldset__description,
.node-form > .form-section > * > .fieldset-wrapper > .fieldset__description {
  grid-column: 1 / -1;
  margin: 0;
}

/**
 * A STRAY IS EITHER A FIELD OR IT IS NOTHING.
 *
 * Three of the form's direct children hold no visible control at all: the two
 * coordinate fields, whose widget renders `<input type="hidden">`, and an empty
 * language wrapper. They are invisible but not absent — as boxes in the flow
 * they were adding 3 × 32px of dead space between the sections, and under the
 * rule below they would each have drawn an empty card.
 *
 * The hidden inputs inside them are still submitted: `display: none` on an
 * ancestor changes nothing about what a form posts.
 */
.node-form > :is(div, .js-form-wrapper):not(.form-actions):not(.form-section):not(:has(input:not([type="hidden"]), select, textarea, .form-item, fieldset, .ck-editor)) {
  display: none;
}

/**
 * …and a stray that IS a field gets the same card as a section.
 *
 * The captcha is the one on this form: a real question, in no group, which
 * would otherwise be the single control on the page sitting on the background
 * between two panels.
 */
.node-form > :is(div.captcha, div.js-form-item, div.form-item, div[class*="field--name-"]):not(.form-actions):has(input:not([type="hidden"]), select, textarea) {
  margin: 0 0 var(--space-l);
  padding: var(--space-l);
  border: 1px solid var(--border-subtle);
  border-radius: var(--card-radius);
  background: var(--surface-1);
}

/* The vertical-tabs shell is an empty container on this form (its panes are
   permission-gated), and a label of its own. It is furniture, not a field. */
.node-form > .form-item--vertical-tabs:not(:has(details, .form-item)) {
  display: none;
}

/* A `<summary>` keeps its marker only if the section is really collapsible. */
.node-form .layout-region__content > details[open] > summary,
.node-form .layout-region__content > details > summary {
  cursor: pointer;
}

/* The required asterisk keeps the accent, at the label's new size. */
.node-form .form-required::after {
  color: var(--me-magenta-300);
  font-size: 1em;
}

/**
 * The controls, at body size.
 *
 * A form control holds what the visitor typed, and 14.7px is small for
 * checking your own phone number in. `--step-0` is the size the rest of the
 * site reads at, which is what an input should be.
 */
.node-form :is(input, select, textarea):not([type="checkbox"]):not([type="radio"]) {
  font-size: var(--step-0);
}

/* Option labels: the same size as body text, because a genre or a day is a
   thing being read rather than a caption. */
.node-form .js-form-type-checkbox > label,
.node-form .js-form-type-radio > label,
.node-form .form-type-checkbox > label,
.node-form .form-type-radio > label,
.node-form label.option {
  font-size: var(--step-0);
  font-weight: var(--weight-regular);
}

/* The tick box itself grows with the label beside it — a 1.15rem box against
   18px text looks like a misprint, and a bigger target is a better target
   (WCAG 2.5.8 asks for 24px; this is 22px plus the label's own hit area). */
.node-form :is(input[type="checkbox"], input[type="radio"]) {
  inline-size: 1.35rem;
  block-size: 1.35rem;
  margin-block-start: 0.15em;
}

/* Descriptions, one step up from the caption size they had. */
.node-form .description,
.node-form .form-item__description,
.node-form .text-format-wrapper .description {
  font-size: var(--step--1);
}

/* ---------------------------------------------------------------------------
 * 12. THE FORM IS NOT THE PANEL — THE SECTIONS ARE
 *
 * One card around the whole form was the previous pass. It held the fields
 * together and told you nothing: six sections inside one box, separated by
 * hairlines, all the same colour and all the same width.
 *
 * The panel is now the section (see 8a above). The form itself is the space
 * they sit in, so it has no surface of its own — a card inside a card is two
 * borders describing the same edge.
 * ------------------------------------------------------------------------ */

/**
 * ONE CONTAINER, WITH THE SECTIONS AS BLOCKS INSIDE IT.
 *
 * Seven cards stacked straight on the page background read as seven things.
 * They are one thing — a single form, submitted once — so they now sit inside
 * one outlined container with the newsletter card's curve, and the section
 * panels are the blocks within it.
 *
 * The container is a WASH, not a second solid card: at full `--surface-1` it
 * would be the same colour as the panels inside it and the whole stack would
 * flatten into one slab. Half-strength keeps the frame legible while letting
 * each section read as a block on top of it.
 */
.submit-page .node-form {
  /*
   * NO BOX OF ITS OWN.
   *
   * The container went from a wash, to the sections' own surface, to nothing:
   * with seven bordered panels inside it there was never a third thing for it
   * to say. An outline hugging a stack of outlined cards is two edges drawing
   * the same line, and on a phone it was two edges inside a 16px gutter.
   *
   * The border goes with the padding and the background — a rule around a box
   * with no inset is the frame without the picture. The sections are the form
   * now, at every width.
   */
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
}

/**
 * The actions are their own block, and the button is in the middle of it.
 *
 * A submit button hard against the left edge under a full-width card reads as
 * the last field of the last section rather than as the end of the form. On
 * its own centred plate it is the page's final step, which is what it is.
 *
 * `.form-actions` is a direct child of the form here — there is no
 * `layout-region-node-footer` on this page, for the reason given in 8a.
 */
.node-form > .form-actions,
.node-form .layout-region-node-footer {
  margin-block-start: var(--space-l);
}

/* The button, and nothing round it. A plate under a single centred button was
   an eighth block in a form that has seven. */
.submit-page .node-form .form-actions {
  padding: var(--space-s) 0 0;
  border: 0;
  border-radius: 0;
  background: none;
  justify-content: center;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  box-shadow: none;
}

/* The advanced group — editors only, and only where Claro's regions exist. */
.submit-page .node-form .layout-region-node-secondary {
  margin-block-start: var(--space-l);
}

.submit-page .node-form .layout-region-node-secondary .layout-region__content {
  display: block;
  padding: var(--space-m);
  border: 1px solid var(--border-subtle);
  border-radius: var(--card-radius);
  background: var(--surface-1);
}

/* ---------------------------------------------------------------------------
 * 12a. THE COORDINATES ARE THE MAP'S OUTPUT
 *
 * Latitude and longitude are filled in by tapping the map, and what they hold
 * is "-33.82809561633873" — seventeen digits that no one submitting a
 * community event types, checks or should be asked to look at.
 *
 * They are hidden only once a working map is on the page: js/script.js marks
 * the form with `add-event-map-ready` after `new google.maps.Map()` returns,
 * so if the key is missing, rejected or blocked the two fields are still there
 * to be typed into. The fields are never removed from the DOM and their values
 * are submitted exactly as before.
 * ------------------------------------------------------------------------ */

.node-form.add-event-map-ready :is(
  .field--name-field-latitude,
  .field--name-field-longitude,
  .field--name-field-lat,
  .field--name-field-lng,
  [id$="field-latitude-wrapper"],
  [id$="field-longitude-wrapper"]
) {
  display: none !important;
}

/**
 * AND THE PAIR THE VISITOR ACTUALLY SEES.
 *
 * The two boxes showing "-33.82809561633873" are not `field_latitude` at all —
 * that one's widget renders `<input type="hidden">` and was never on screen.
 * They are the `lat` and `lng` halves of a GEOLOCATION field, `field_map`,
 * inside the fieldset whose legend reads "Map". Hiding the field named
 * "latitude" was therefore hiding something already invisible while the
 * visible pair stayed exactly where it was.
 *
 * Matched by the input's name ending in `[lat]` / `[lng]` rather than by the
 * field's machine name, so this holds for a Geofield or a Geolocation field
 * whatever it is called. The fieldset itself stays — it is where the map goes.
 */
.node-form.add-event-map-ready .form-item:has(> input[name$="[lat]"]),
.node-form.add-event-map-ready .form-item:has(> input[name$="[lng]"]),
.node-form.add-event-map-ready .form-item:has(> input[name$="[lon]"]) {
  display: none !important;
}

/**
 * `!important` on both, and it is earned.
 *
 * These wrappers are shown and hidden at runtime by Drupal's #states and by
 * the conditional_fields module, and both do it by writing
 * `style="display: block"` straight onto the element. An inline style beats
 * any selector, so without this the fields reappeared the moment the visitor
 * chose "Other" as the venue — the one case where they are guaranteed to be
 * on screen.
 */

/**
 * A hidden element stays hidden.
 *
 * `[hidden]`'s `display: none` comes from the user-agent stylesheet, and every
 * author rule beats it — including `.node-form .form-item { display: grid }`
 * two hundred lines above. Anything this theme's JavaScript hides with the
 * `hidden` property would otherwise still be on the page.
 */
.node-form [hidden] {
  display: none !important;
}


/* ---------------------------------------------------------------------------
 * 12b. NOTHING LEAVES THE CARD ON A PHONE
 *
 * A fieldset's initial `min-inline-size` is `min-content`, not 0 — it refuses
 * to shrink below its widest child. This form is fieldsets all the way down
 * (a section, then a widget, then a date pair inside that), so a single
 * unshrinkable control at the bottom pushes every box above it past the screen
 * edge. That is the horizontal drift on a phone, and it is why it only shows
 * on the right.
 *
 * Belt and braces: the floor is restated for every box in the chain, and every
 * control is capped at its container. `input[size="60"]` is a 480px intrinsic
 * width, and Drupal writes it on nearly every text field on this page.
 * ------------------------------------------------------------------------ */

.node-form :is(fieldset, .fieldset-wrapper, .form-item, .js-form-item, .form-wrapper, .js-form-wrapper, .details-wrapper, .form-section) {
  min-inline-size: 0;
  max-inline-size: 100%;
}

.node-form :is(input, select, textarea, .form-managed-file, .image-widget, .ck, .ck-editor, .select2-container) {
  max-inline-size: 100%;
  box-sizing: border-box;
}

/* A description with a long unbroken string — a coordinate, a URL — is the
   other thing that will not shrink. */
.node-form :is(.description, .form-item__description, .fieldset__description) {
  overflow-wrap: anywhere;
}

/* CKEditor's toolbar is a row of thirty buttons; on a phone it must wrap
   rather than set the width of everything around it. */
.node-form .ck.ck-toolbar {
  flex-wrap: wrap;
}

/* The filter guidelines list under "Name" indents by 40px of its own. */
.node-form .js-filter-guidelines ul {
  margin: 0;
  padding-inline-start: var(--space-m);
}

/* ---------------------------------------------------------------------------
 * 13. THE VENUE MAP PICKER
 *
 * Built by the add_event module's js/script.js: tap the map, it drops a pin,
 * writes the latitude and longitude and fills the custom venue address. The
 * module creates the canvas immediately above the Latitude field and gives it
 * this class; everything below is the box it lives in.
 *
 * A map with no height renders as nothing at all, which is indistinguishable
 * from a broken key — so the height is stated here and the module's JavaScript
 * carries its own floor for any theme that does not style this class.
 * ------------------------------------------------------------------------ */

.add-event-map {
  grid-column: 1 / -1;
  block-size: clamp(16rem, 32vw, 24rem);
  margin-block-end: var(--space-s);
  border: 1px solid var(--border-strong);
  border-radius: var(--card-radius);
  overflow: hidden;
  background: var(--surface-2);
}

/* Google paints its own white chrome inside the canvas; the frame around it is
   the theme's. Nothing here reaches into the map's own DOM — those class names
   are Google's and change without notice. */
.add-event-map * {
  max-inline-size: none;
}

/**
 * The map's failure states.
 *
 * When there is no key, or Google rejects the one there is, or the script
 * cannot be fetched, the module writes a message into the same box. An empty
 * grey rectangle is indistinguishable from a broken feature; a box that says
 * "the venue map needs a Google Maps API key" is a job someone can do.
 *
 * Dashed rather than solid, like the image upload above it: this is a slot
 * waiting for something rather than a thing that is there.
 */
.add-event-map--message {
  display: grid;
  align-content: center;
  gap: var(--space-2xs);
  block-size: auto;
  min-block-size: 10rem;
  padding: var(--space-l);
  border-style: dashed;
  text-align: center;
}

.add-event-map__title {
  margin: 0;
  color: var(--text-primary);
  font-size: var(--step--1);
  font-weight: var(--weight-bold);
}

.add-event-map__hint {
  margin: 0;
  color: var(--text-muted);
  font-size: var(--step--2);
  line-height: var(--leading-normal);
  overflow-wrap: anywhere;
}


/* ---------------------------------------------------------------------------
 * 14. THE GENRE LIMIT
 *
 * "Only can select two genres ." was a Bootstrap modal in a views block, and
 * there is no Bootstrap on the site any more: the markup renders as a line of
 * loose text under the Submit button with a stray × beside it. It is hidden
 * here and the rule it was trying to state is enforced in js/node-form.js,
 * where the person is looking — under the checkboxes they just ticked.
 * ------------------------------------------------------------------------ */

.view--modal,
#modal-div {
  display: none;
}

.field-limit {
  grid-column: 1 / -1;
  display: flex;
  align-items: flex-start;
  gap: var(--space-3xs);
  margin-block-start: var(--space-2xs);
  padding: var(--space-2xs) var(--space-xs);
  border: 1px solid var(--me-magenta);
  border-radius: var(--radius-s, 0.5rem);
  background: color-mix(in srgb, var(--me-magenta) 14%, transparent);
  color: var(--text-primary);
  font-size: var(--step--1);
  line-height: var(--leading-normal);
}

.field-limit[hidden] {
  display: none;
}

.field-limit__icon {
  flex: none;
  inline-size: 1.15rem;
  block-size: 1.15rem;
  color: var(--me-magenta-300);
}

/* The tick box a limit has closed off: still readable, visibly not available. */
.field-limit-reached input[type="checkbox"]:not(:checked) {
  opacity: 0.45;
}

.field-limit-reached input[type="checkbox"]:not(:checked) + label {
  color: var(--text-secondary);
}

/* ---------------------------------------------------------------------------
 * 15. THE DATE FIELDS
 *
 * `<input type="date">` is the browser's control: its format follows the
 * operating system's locale — an Australian council's form was showing
 * mm/dd/yyyy — and its calendar is a light popup in a dark page that cannot be
 * styled. js/node-form.js swaps each one for the theme's own date field, the
 * same control the search panel uses; css/components/datepicker.css paints it.
 *
 * The original input is kept, turned into the hidden ISO value the calendar
 * writes to, so what Drupal receives is exactly what it received before.
 * ------------------------------------------------------------------------ */

.node-form .datefield {
  inline-size: 100%;
  max-inline-size: 100%;
}

/* A date and a time side by side rather than stacked: they are one answer. */
.node-form .field--type-datetime .fieldset-wrapper {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xs) var(--space-s);
}

.node-form .field--type-datetime .fieldset-wrapper > * {
  flex: 1 1 11rem;
  min-inline-size: 0;
}

/**
 * A MESSAGE IS A ROW, NOT A COLUMN.
 *
 * `> *` above makes every direct child an 11rem-ish flex item, and after a
 * failed submit the children are not only the controls: Drupal's error
 * paragraph is one too. So the sentence was laid out as a column BESIDE the
 * date and time, wrapping to four or five words a line, and a second copy
 * (see below) took another column on the other side — which is what the
 * "error appears left and right of the field" report was.
 *
 * `100%` basis puts each message on a line of its own, under the controls it
 * is about.
 */
.node-form .field--type-datetime .fieldset-wrapper > :is(
  .form-item__error-message,
  .datetime-warning
),
.node-form .field--type-datetime .fieldset-wrapper > div:not([id]):has(> .form-error__rule) {
  flex: 1 1 100%;
}

/**
 * THE SAME ERROR, PRINTED TWICE BY TWO TEMPLATES THAT CANNOT SEE EACH OTHER.
 *
 * An error on a datetime widget reaches both the fieldset that wraps it and
 * the datetime wrapper inside it, and each prints what it was given:
 *
 *   templates/form/fieldset.html.twig        <p class="form-item__error-message">
 *   core datetime-wrapper.html.twig          <div><span class="form-error__rule">
 *
 * Neither is wrong on its own. Together they say the same sentence twice,
 * and a screen reader reads it twice.
 *
 * HIDDEN IN CSS RATHER THAN REMOVED IN TWIG, ON PURPOSE. Overriding
 * datetime-wrapper to drop `{{ errors }}` would also silence the fields that
 * have NO wrapping fieldset — `field_end_date` on this very form is one —
 * and their message would vanish with nothing to replace it. The condition
 * that actually matters is "an ancestor has already printed this", and
 * `:has()` can express exactly that: the inner copy goes only when the
 * wrapper above it is already showing one.
 *
 * `div:not([id])` is the discriminator against the widget's own
 * `<div id="edit-…-value">`, which holds the date and time controls and must
 * never be hidden.
 */
.node-form .fieldset-wrapper:has(> .form-item__error-message)
  > div:not([id]):has(> .form-error__rule) {
  display: none;
}

/* The mismatch warning under Finish. */
.node-form .datetime-warning {
  grid-column: 1 / -1;
  margin-block-start: var(--space-2xs);
  color: var(--me-magenta-300);
  font-size: var(--step--1);
}


/* ---------------------------------------------------------------------------
 * 16. A FIELD WAITING ON ANOTHER FIELD
 *
 * Set by js/node-form.js on a row whose condition is not yet met — "Day of the
 * week" before a recurring type has been chosen. `!important` because Drupal's
 * #states shows a row by writing an inline `display`, and this condition is
 * the narrower of the two: both must be true for the row to appear.
 * ------------------------------------------------------------------------ */

.node-form .me-awaiting-choice {
  display: none !important;
}

/* ---------------------------------------------------------------------------
 * 15. THE SUBMIT-TIME MESSAGE ON THE EVENT FORM
 *
 * The original add-event page did something better than "Title is not valid":
 * on a failed submit it put the RULE under the field in the brand colour and
 * what you had actually typed beside it in grey —
 *
 *     Characters should be in between 2-50.   Total characters typed: 1.
 *
 * add_event.module builds both halves (see _add_event_rule_error()); this is
 * the half that makes them look like two different kinds of thing. Scoped to
 * `.add-event-form`, the class that module puts on the form, so no other form
 * on the site changes.
 * ------------------------------------------------------------------------ */
.add-event-form {
  /*
   * NOT --me-magenta, AND THE DIFFERENCE IS DELIBERATE.
   *
   * Sampled from the original screenshot, the rule text is the same colour as
   * the required asterisk — the brand magenta. On this form's panel that
   * measures 3.63:1 against white-on-dark, and the message is bold 14.7px,
   * which is not "large text" under WCAG, so it needs 4.5:1. An error nobody
   * can read is the one message on the page that has to be legible.
   *
   * --me-magenta-300 is the token the theme already keeps for "accent TEXT on
   * any dark surface": same pink, 7.08:1. Set this to var(--me-magenta) if an
   * exact match to the old page matters more than the contrast.
   */
  --form-error-rule: var(--me-magenta-300);
}

/*
 * No badge here.
 *
 * Every other form on the site prefixes an error with a round "!" in
 * --me-error red. Beside a magenta rule that reads as two warnings about
 * different things, and the original page had none. Dropping it does not
 * leave the error carried by colour alone: the text itself changes, to the
 * rule you missed and the count you typed, which is what WCAG 1.4.1 asks for.
 */
.add-event-form .form-item__error-message {
  display: block;
  gap: 0;
  color: inherit;
  font-weight: var(--weight-regular);
  /*
   * The same size as a description, because it is standing in for one.
   * form.css sets errors at --step--2 while this file lifts descriptions to
   * --step--1, so without this line the message a submitter most needs to
   * read came out 11.6px against the 14.3px note it replaces.
   */
  font-size: var(--step--1);
}

.add-event-form .form-item__error-message::before {
  content: none;
}

.add-event-form .form-error__rule {
  color: var(--form-error-rule);
  font-weight: var(--weight-bold);
}

.add-event-form .form-error__actual {
  color: var(--text-muted);
  font-weight: var(--weight-regular);
}

/*
 * THE RULE IS PRINTED ONCE, NOT TWICE.
 *
 * The note under a field and the error message are now the same sentence, by
 * design — so a field that fails would otherwise show it twice, once in pink
 * from the error and again in grey from the description directly beneath.
 * The error is the more useful of the two, because it carries the count, so
 * the description stands down while there is an error to read.
 *
 * This also retires the theme's own `.form-item--error .description` rule for
 * this form, which turned the description red: nothing to recolour if nothing
 * is shown.
 */
.add-event-form .form-item--error .form-item__description,
.add-event-form .form-item--error .description {
  display: none;
}

/*
 * THE LIVE COUNT, WHILE TYPING.
 *
 * js/live-rules.js in add_event writes the same two spans into the field's
 * note that the server writes into its error message, so there is one design
 * here and not two. The only difference is which state the field is in:
 *
 *   typing, within the rule  -> the whole note stays muted, as a note
 *   typing, outside it       -> the rule half turns, exactly as on submit
 *
 * `.is-rule-broken` is the class the script toggles. It sits on the form item
 * rather than on the note so the pair can be styled together if the field
 * itself ever needs to react as well.
 */
.add-event-form .form-item__description .form-error__rule,
.add-event-form .form-item__description .form-error__actual {
  color: var(--text-muted);
  font-weight: var(--weight-regular);
}

.add-event-form .is-rule-broken .form-item__description .form-error__rule {
  color: var(--form-error-rule);
  font-weight: var(--weight-bold);
}

/*
 * A note the script is driving must stay visible.
 *
 * The rule above this section hides the description whenever the item carries
 * `form-item--error`, because after a failed submit the server's message says
 * the same thing. The script removes that class on the first keystroke, but
 * this is the belt to that braces: once the live count is in the note, the
 * note is the thing to read.
 */
.add-event-form .form-item--error.is-rule-broken .form-item__description,
.add-event-form .is-rule-broken .form-item__description {
  display: block;
}
