@layer components {
  /* The way-in screens are in auth.css, with the mark and the sentence that
     stand above the card. */

  .form {
    display: grid;
    gap: var(--space);
  }

  .form__section {
    display: grid;
    gap: var(--space);
    padding-block-end: var(--space-and-half);

    &:not(:last-of-type) {
      border-block-end: var(--border);
    }
  }

  .form__legend {
    margin: 0;
    font-size: var(--text-body);
    font-weight: var(--weight-bold);
  }

  .form__row {
    --form-column-min: 12rem;

    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(var(--form-column-min), 1fr));
    gap: var(--space);
  }

  /* A row of fields that each carry a paragraph of explanation under them — a
     channel's settings, drawn from another company's catalogue. Wider columns
     and a looser gap, because a description in a column this narrow is a column
     of single words. A variant rather than a second grid somewhere else, so the
     auto-fit behaviour is declared once. */
  .form__row--roomy {
    --form-column-min: 19rem;

    gap: var(--space-and-half);
    align-items: start;
  }

  .form__field {
    display: grid;
    gap: var(--space-quarter);
    position: relative;

    label {
      font-size: var(--text-small);
      font-weight: var(--weight-medium);
      color: var(--color-ink-soft);
    }
  }

  /* The box you type in, and the one place its chrome is decided.
   *
   * It lived inside `.form__field` and only there, so a control anywhere else came
   * out as the browser's own square, unpadded, system-faced input standing next to
   * fields that were none of those — which is exactly what the settings rows on the
   * pricing and availability screens looked like.
   *
   * A selector list rather than a fifth copy of the six declarations, and rather
   * than a `.field` class: a class would have to be added at every call site, and
   * the three wrappers below want to be *varieties* of this rather than users of
   * it. That is the "One field, not four" debt COMPONENTS.md records and this is
   * not it — this is the smaller thing, one rule with a second consumer, and a
   * third joins by being named here.
   *
   * Harmless inside `.input-group`: that rule comes later and takes the border and
   * the leading padding back off, which is what makes a wrapped control read as one
   * box. What it now inherits is the block padding, so a field inside a group and a
   * field standing on its own are finally the same height. */
  :is(.form__field, .setting-row__control) :is(input, select, textarea) {
    padding: var(--field-padding-block) var(--field-padding-inline);
    border: var(--border);
    border-radius: var(--radius);
    background: var(--color-canvas);
    font: inherit;
    color: inherit;
    inline-size: 100%;
  }

  :is(.form__field, .setting-row__control) textarea {
    resize: vertical;
    line-height: var(--leading-loose);
  }

  /* A label with something beside it — an ⓘ, a character count, a link to
     whatever it is about. The label is still the label and still points at its
     field; this only stops the two stacking, which is what .form__field's grid
     would otherwise do to them. */
  .form__label-row {
    display: flex;
    align-items: center;
    gap: var(--space-quarter);
  }

  /* A button standing in a row of fields. It carries no label, so without this
     it sits a label's height above everything it is beside. */
  .form__field--action {
    align-content: end;
  }

  .form__field--time {
    --form-field-width: 12rem;

    max-inline-size: var(--form-field-width);
  }

  /* A heading and the sentence under it, inside a form or a grid.
   *
   * The heading gives up the browser's own margin, which is what caused the hole
   * over "Notifications on this device": every container in this app that holds
   * one is a grid with a gap, so the margin is a second answer to the same
   * question and the two add up. The gap is the spacing. */
  .form__heading {
    display: grid;
    gap: var(--space-quarter);

    :is(h2, h3) {
      margin: 0;
    }

    p {
      margin: 0;
    }
  }

  /* Between two forms on one screen — your name and your password is the first
     pair, and the organization and property settings screens are heading for the
     same shape. A rule rather than a gap, because the two are separate decisions
     with separate buttons and a gap alone reads as one long form somebody
     scrolled.

     Named for what it does, not for the screen it was written on: it was
     `.profile-divide`, in this shared stylesheet, which is the thing this diff
     renamed `.property-switcher` and `.property-details__section` for. A rule
     between two forms is the most general object there is. */
  .form-divide {
    margin-block: var(--space-double);
    border: 0;
    border-block-start: var(--border-faint);
  }

  .form__hint {
    margin: 0;
    font-size: var(--text-small);
    color: var(--color-ink-soft);
  }

  .form__hint--warning {
    color: var(--color-negative);
  }

  .input-group {
    display: flex;
    align-items: center;
    gap: var(--space-half);
    border: var(--border);
    border-radius: var(--radius);
    padding-inline-start: var(--field-padding-inline);
    background: var(--color-canvas);

    input {
      /* Shrinkable, or the prefix wraps above the box. An input carries an
       * intrinsic width of about twenty characters and a flex item does not go
       * below its intrinsic minimum unless told to, so "USD" plus a full-width
       * field overflowed its own border and the browser wrapped them into two
       * rows inside one outline. */
      flex: 1;
      min-inline-size: 0;
      border: none;
      padding-inline-start: 0;
    }
  }

  /* Wrapped controls — where the box around the input is what reads as the input.
   *
   * These four all draw the border themselves and put a bare control inside it.
   * Focusing the input then draws the global ring from _global.css *inside* that
   * border, and a ring inside a border reads as two boxes rather than as one
   * focused control. So the wrapper takes the ring, and the input it wraps gives
   * up its own.
   *
   * Only the field itself, and the child combinator is doing that work. These
   * wrappers hold other things that are genuinely focusable and genuinely need a
   * ring of their own: the counter's − and +, a chip's ×, Clear and Done in a
   * combobox footer, and Send in a composer. A descendant selector here silently
   * took the focus ring off all of them.
   *
   * .combobox__field and .conversation__field are listed here rather than in
   * their own stylesheets for the reason all four footers are in footer.css: it
   * is one decision, and four copies of a decision is how two of them end up
   * wrong. Anything that grows a border around an input belongs on this list. */
  .input-group,
  .counter__control,
  .combobox__field,
  .conversation__field {
    &:focus-within {
      outline: var(--border-width-heavy) solid var(--color-accent);
      outline-offset: var(--space-eighth);
    }

    & > input:focus-visible,
    & > textarea:focus-visible {
      outline: none;
    }
  }

  /* A unit after the number — "%", "nights", "guests". The prefix has been here
   * since the first currency field and a suffix is the same idea; the screens
   * that wanted one were reaching for a bare span beside the box, which sat
   * outside the border and outside the focus ring.
   *
   * The end padding is brought by :has() rather than declared on the block,
   * because a group with a prefix and no suffix should not carry a gap at the end
   * where nothing is. The input grows so the unit sits at the far edge, which is
   * what makes a column of them line up with each other. */
  /* The number hugs its unit. A prefix puts the unit first, so the figure sits
   * against it on the left; a suffix puts it last, so the figure goes to the
   * right. Left alone, "1" sat at one end of the box and "nights" at the other
   * and they read as two unrelated things. */
  .input-group:has(.input-group__suffix) {
    padding-inline-end: var(--field-padding-inline);

    input {
      padding-inline-end: 0;
      text-align: end;
    }
  }

  .input-group__prefix,
  .input-group__suffix {
    flex-shrink: 0;
    color: var(--color-ink-soft);
  }

  /* Buttons live in button.css; the validation summary is a callout. */

  /* The photo in the "what does this show" dialog. The question cannot be answered
     from a filename, so the picture is the first thing in the body. Its own block
     rather than .gallery__image, which is a tile in a grid and takes its size from
     the column it is in. */
  .image-form__photo {
    --image-form-photo-height: 16rem;

    inline-size: 100%;
    max-block-size: var(--image-form-photo-height);
    margin-block-end: var(--space);
    border-radius: var(--radius);
    object-fit: cover;
  }

  /* Address suggestions */
  .suggestions {
    --suggestions-max-height: 15rem;

    position: absolute;
    inset-block-start: 100%;
    inset-inline: 0;
    z-index: var(--z-popup);
    margin: var(--space-quarter) 0 0;
    padding: var(--space-half);
    list-style: none;
    background: var(--color-canvas);
    border: var(--border);
    border-radius: var(--radius-large);
    box-shadow: var(--shadow-overlay);
    max-block-size: var(--suggestions-max-height);
    overflow-y: auto;
  }

  .suggestions li + li {
    border-block-start: var(--border-faint);
  }

  .suggestions__item {
    display: grid;
    gap: var(--space-eighth);
    inline-size: 100%;
    padding: var(--space-three-quarters) var(--space-half);
    border: 0;
    border-radius: var(--radius-small);
    background: transparent;
    color: var(--color-ink);
    font: inherit;
    line-height: var(--leading-normal);
    text-align: start;
    cursor: pointer;

    &:hover,
    &:focus-visible {
      background: var(--color-highlight);
    }
  }

  .suggestions__street {
    font-size: var(--text-normal);
    font-weight: var(--weight-semibold);
  }

  .suggestions__place {
    color: var(--color-ink-soft);
    font-size: var(--text-small);
  }

  .map-preview {
    inline-size: 100%;
    block-size: auto;
    border-radius: var(--radius);
    border: var(--border);
  }

  /* Counter */
  .counter {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space);
    padding-block: var(--space-half);
  }

  /* Several of them in a column, as one panel of rows rather than three
     separate controls: the padding comes inside so the rules meet the panel's
     edges, and each one after the first is ruled off from the one above.

     A variant here rather than `.wizard-counters .counter` there, which is a
     consumer setting padding and a border on another component's box — the
     thing that makes a primitive impossible to change later. */
  .counter--stacked {
    padding-inline: var(--space);
  }

  .counter--stacked + .counter--stacked {
    border-block-start: var(--border-faint);
  }

  .counter__text {
    display: grid;
  }

  .counter__label {
    font-size: var(--text-body);
    font-weight: var(--weight-medium);
    color: var(--color-ink);
  }

  .counter__hint {
    font-size: var(--text-small);
    color: var(--color-ink-soft);
  }

  .counter__control {
    display: flex;
    align-items: center;
    gap: var(--space-quarter);
    border: var(--border);
    border-radius: var(--radius-pill);
    padding: var(--space-eighth);
    background: var(--color-canvas);
  }

  .counter__button {
    inline-size: var(--control-size-small);
    block-size: var(--control-size-small);
    border: none;
    border-radius: var(--radius-circle);
    background: none;
    font-size: var(--text-body);
    cursor: pointer;
    color: var(--color-ink-soft);

    &:hover {
      background: var(--color-highlight);
      color: var(--color-ink);
    }
  }

  .counter__input {
    --counter-input-width: 3.5rem;

    inline-size: var(--counter-input-width);
    border: none !important;
    text-align: center;
    font-variant-numeric: tabular-nums;
    background: none !important;

    &::-webkit-outer-spin-button,
    &::-webkit-inner-spin-button {
      -webkit-appearance: none;
      margin: 0;
    }
  }

  /* Checklist */
  .checklist {
    --checklist-column-min: 14rem;

    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(var(--checklist-column-min), 1fr));
    gap: var(--space-quarter);
  }

  .checklist__item {
    --checklist-check-size: 1.05rem;

    display: flex;
    align-items: center;
    gap: var(--space-half);
    padding: var(--field-padding-block) var(--field-padding-inline);
    border-radius: var(--radius);
    cursor: pointer;

    &:hover {
      background: var(--color-highlight);
    }

    input {
      accent-color: var(--color-accent);
      inline-size: var(--checklist-check-size);
      block-size: var(--checklist-check-size);
    }
  }

  /* A compact, visible set of options. The checkbox stays native and visible;
     the label becomes the pill, so selection is never communicated by colour
     alone and the control keeps its platform keyboard behaviour. */
  .checklist--chips {
    --checklist-column-min: 11rem;
  }

  .checklist--chips .checklist__item {
    border: var(--border);
    border-radius: var(--radius-pill);
    background: var(--color-canvas);
    transition: background var(--transition-fast), border-color var(--transition-fast);

    &:has(input:checked) {
      border-color: var(--color-accent);
      background: var(--color-highlight);
      color: var(--color-accent);
      font-weight: var(--weight-medium);
    }
  }
}
