@layer components {
  /* A form does not have a width of its own. The panel it sits in takes the
     column like every other panel; the things you actually type into take the
     measure, because a 1024px email field is not generous, it is just wide.
     Two widths on the page, one nested inside the other. */
  /* Descendant, not child: form_with renders its own <form> inside the panel,
     so the fields are grandchildren of .form and a child selector reaches none
     of them. */
  .form .field,
  .form .row,
  .form .button,
  .form input.button { max-width: var(--measure); }

  .field { display: flex; flex-direction: column; gap: var(--space); }


  /* The shared controls.

     One field, drawn once. The design is the comment composer's, which is the
     surface in this product people write the most into and the one that was
     right: sunk paper rather than white, the quietest line the tokens have
     rather than the strong one, and the writing-surface corner rather than the
     small-control corner. Everything typed into anywhere now agrees with it —
     the capture bar, the join link, the prefix, an email address — and the
     three states say the same three things everywhere: at rest it is a shape
     to fill, under the pointer its edge firms up, and on focus it lifts to
     white paper with the accent around it.

     Sunk-at-rest is what makes a field read as a field without a heavy border
     doing it: the tint is the affordance, so the line can stay faint. A white
     box on white paper needs its outline to be seen, which is why these used
     to carry --line-strong, and a page of strong-bordered boxes is a form
     rather than a page you work on.

     A component that customises one of these must say so with both classes —
     `.input.capture__input`, not `.capture__input` — because a single class
     ties with this rule on specificity, and a tie is settled by which file
     Propshaft happened to link last. That is filename order, which is to say
     alphabetical, which is to say nothing at all about intent: `capture.css`
     and `joinlink.css` both lost silently to this rule for months, and the
     designs written in them were never once drawn.

     The tokens file makes the same point about @layer deciding which layer
     wins. This is the level below it: inside a layer, source order still
     decides, and source order here is an accident of the alphabet. */
  .input, .select, .textarea {
    font: inherit;
    font-size: var(--text-base);
    color: var(--ink);
    background: var(--surface-sunk);
    border: 1.5px solid var(--line);
    border-radius: var(--radius);
    padding: 0 var(--space-2);
    height: var(--control-h);
    width: 100%;
    transition: border-color var(--transition), background var(--transition), var(--responds);
  }

  .textarea { height: auto; min-height: 9rem; padding: var(--space-2); line-height: var(--leading-body); resize: vertical; }

  /* Hover before focus, and the order is the whole of it: they are the same
     specificity, so a field that is focused *and* under the pointer takes
     whichever is written last. Written the other way round, the accent ring
     you just landed drops back to a grey line the moment the mouse arrives. */
  .input:hover, .select:hover, .textarea:hover { border-color: var(--line-strong); }
  .input:focus, .select:focus, .textarea:focus { background: var(--surface); border-color: var(--accent); }
  .input::placeholder, .textarea::placeholder { color: var(--ink-faint); }

  /* A disabled field is a fact rather than a control — the email address on
     the profile page is the only one — so it loses the hover and says plainly
     that there is nothing to press. */
  .input:disabled, .select:disabled, .textarea:disabled {
    color: var(--ink-muted);
    cursor: not-allowed;
  }

  .input:disabled:hover, .select:disabled:hover, .textarea:disabled:hover { border-color: var(--line); }

  /* A file field is a button the browser draws, and it draws it in its own
     furniture unless told otherwise. Given the product's button rather than
     Chrome's, so Choose file next to Send invitation is not two design
     systems in one form. */
  .input[type="file"] {
    display: flex;
    align-items: center;
    padding-inline: var(--space);
    /* The name of the chosen file is the browser's own text and it is not
       elastic. Clipped rather than allowed to run out of the box, which is
       what it did at 400px. */
    overflow: hidden;
  }

  .input[type="file"]::file-selector-button {
    font: inherit;
    font-size: var(--text-xs);
    font-weight: var(--weight-bold);
    min-height: var(--control-h-sm);
    margin-inline-end: var(--space-2);
    padding-inline: var(--space-2);
    border: 1.5px solid var(--line-strong);
    border-radius: var(--radius);
    background: transparent;
    color: var(--ink-muted);
    cursor: pointer;
    transition: background var(--transition), color var(--transition),
                border-color var(--transition);
  }

  .input[type="file"]::file-selector-button:hover {
    background: var(--surface-hover);
    border-color: var(--ink-faint);
    color: var(--ink);
  }
}
