/*
 * form-core.css
 * .field owns its own box; it has no shared base the way btn/pill/badge
 * share chip.css. Tones come from tones.css — .field reads --bg-mix for
 * state borders.
 */

.field {
  --field-bg:     var(--surface);
  --field-color:  var(--ink);

  /* Any tone class sets the border; untoned falls back to the rule color.
     No tone-name list — see the recipe note in surface.css. */
  --field-border: var(--bg-mix, var(--rule-strong));

  /*
   * Full width is right in a form column and wrong everywhere else — a
   * <select> in a toolbar, a search box in a topbar, a number input in a
   * .field-row. It is a token so those cases set a value instead of
   * fighting `width: 100%` with an override:
   *
   *   <select class="field" style="--field-inline-size: auto">
   *   .toolbar .field { --field-inline-size: auto; }
   *
   * `auto` gives the control its intrinsic size, which is what a bare
   * <select> or a short <input> wants.
   */
  display:     block;
  inline-size: var(--field-inline-size, 100%);
  /* Vertical padding is shared with .btn — see --control-padding-block. */
  padding:     var(--control-padding-block) var(--space-lg);
  font-size:   var(--text-md);
  line-height: 1.25rem;

  background:    var(--field-bg);
  color:         var(--field-color);
  /*
   * A Field's border is its own decision — an input that reads as a box
   * and a Card hairline are not the same weight in every design — so it
   * has an escape, and it follows --border-width by default rather than
   * being pinned at 1px.
   */
  border:        var(--field-border-width, var(--border-width)) solid var(--field-border);
  border-radius: var(--field-radius);
  font-family:   var(--font-primary);

  transition: border-color var(--motion-fast), box-shadow var(--motion-fast);
}
.field::placeholder { color: var(--ink-mute); }

/*
 * The border adopts the tone on focus; the ring itself comes from
 * focus.css, which reads the same --bg-mix so the two always agree.
 */
.field:focus {
  border-color: var(--bg-mix, var(--ring, var(--color-primary)));
}

.field:disabled {
  background: color-mix(in srgb, var(--ink) 4%, var(--surface));
  color:      var(--ink-mute);
  cursor:     not-allowed;
}

/* ── Type-specific tweaks ─────────────────────────────────────── */
textarea.field {
  resize:      vertical;
  min-height:  80px;
  font-family: var(--font-primary);
}

select.field {
  appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='%236b7280' stroke-width='1.5'><polyline points='3,5 6,8 9,5'/></svg>");
  background-repeat:   no-repeat;
  background-position: right 12px center;
  background-size:     12px;
  padding-right:       36px;
  cursor:              pointer;
}

/* ── Composition helpers ──────────────────────────────────────── */
.field-group {
  display:        flex;
  flex-direction: column;
  gap:            var(--space-xs);
}
.field-group > label {
  font-size:   var(--text-sm);
  font-weight: 500;
  color:       var(--ink-soft);
}

/* Tone class colors the hint; untoned stays muted. No tone-name list. */
.field-hint {
  font-size: var(--text-xs);
  color:     var(--bg-mix, var(--ink-mute));
}

.field-check {
  display:     inline-flex;
  align-items: center;
  gap:         var(--space-sm);
  cursor:      pointer;
  font-size:   var(--text-md);
  color:       var(--ink);
}
/*
 * The tone usually sits on the label, not the input — but --bg-mix is
 * element-scoped (inherits:false), so the input cannot see it. The label
 * derives it into a normal inheriting property and passes that down, the
 * same shape tables and dialogs use.
 *
 * The input still checks its own --bg-mix first, so a tone class works on
 * either element.
 */
.field-check {
  --check-accent: var(--bg-mix, var(--color-primary));
}
/*
 * `:not(.switch)` is load-bearing. This rule is (0,1,1) and `.switch`
 * below is (0,1,0), so without the exclusion it wins and squashes the
 * switch to a 16x16 circle — inside the very markup the switch section
 * documents. A switch whose entire affordance is its shape rendered as a
 * small round checkbox, and only building a real settings screen showed
 * it.
 */
.field-check input:not(.switch) {
  width:        16px;
  height:       16px;
  margin:       0;
  cursor:       pointer;
  accent-color: var(--bg-mix, var(--check-accent));
}

/* The switch has its own box. `accent-color` does nothing on it — it is
   appearance:none and paints its own track — so it takes the label's
   derived accent through --check-accent instead, below. */
.field-check .switch {
  margin: 0;
}
.field-check:has(input:disabled) {
  opacity: 0.55;
  cursor:  not-allowed;
}

/*
 * ── Native validation drives the tone ───────────────────────────
 *
 * `:user-invalid` matches only after the user has actually interacted
 * with the field — unlike `:invalid`, which matches an empty required
 * input the instant the page loads and shouts at someone who has not
 * typed anything yet.
 *
 * Setting --bg-mix is the whole implementation: the border, the focus
 * ring and any .field-hint in scope already derive from it, so one line
 * turns the entire field red at the right moment with no JavaScript and
 * no class to toggle. This is the same principle as [aria-current] in
 * nav.css — let the platform own the state.
 *
 * Opt into the positive case per form if you want it:
 *   .field:user-valid { --bg-mix: var(--color-success); }
 */
.field:user-invalid {
  --bg-mix: var(--color-danger);
}

/*
 * ── Switch ──────────────────────────────────────────────────────
 *
 *   <label class="field-check">
 *     <input type="checkbox" role="switch" class="switch" checked>
 *     <span>Email notifications</span>
 *   </label>
 *
 * A real checkbox with role="switch", so checked state, keyboard
 * activation and label association are all native (Principle 4).
 *
 * The knob is a background-image rather than a pseudo-element. An
 * <input> is a replaced element, and pseudo-elements on replaced
 * elements are not guaranteed by spec — they happen to work on
 * appearance:none checkboxes in current browsers, but a background
 * gradient is defined behavior everywhere.
 */
.switch {
  appearance:    none;
  flex-shrink:   0;
  inline-size:   2.25rem;
  block-size:    1.25rem;
  border-radius: 999px;
  cursor:        pointer;

  background-color: var(--rule-strong);
  background-image: radial-gradient(circle at center, #fff 42%, transparent 44%);
  background-size:     1rem 1rem;
  background-repeat:   no-repeat;
  background-position: 0.125rem center;

  transition: background-color var(--motion-base) var(--motion-ease),
              background-position var(--motion-base) var(--motion-ease);
}
/*
 * The checked track reads the same three-step chain the checkbox does:
 * a tone on the switch itself, else the one the .field-check label
 * derived into --check-accent, else primary. Without the middle step a
 * tone on the label cannot cross to the input, because --bg-mix is
 * element-scoped; without the last step a switch outside a .field-check
 * would resolve to nothing and render untinted.
 */
.switch:checked {
  background-color:    var(--bg-mix, var(--check-accent, var(--color-primary)));
  background-position: calc(100% - 0.125rem) center;
}
/* Focus ring: focus.css. */
.switch:disabled {
  opacity: 0.5;
  cursor:  not-allowed;
}

/*
 * ── Field row — inputs with attached addons ─────────────────────
 *
 *   <div class="field-row">
 *     <span class="field-addon">$</span>
 *     <input class="field" type="number" inputmode="decimal">
 *     <span class="field-addon">.00</span>
 *   </div>
 *
 *   <div class="field-row">
 *     <input class="field" type="search">
 *     <button class="btn">Search</button>
 *   </div>
 *
 * An addon is decoration. If it carries meaning the input does not,
 * put that meaning in the <label> or a .field-hint — a screen reader
 * user should not have to infer "dollars" from a glyph beside the box.
 */
.field-row {
  display:     flex;
  align-items: stretch;
}
/* Square every internal edge, then round the outer two. */
.field-row > * {
  border-radius: 0;
}
.field-row > :first-child {
  border-start-start-radius: var(--field-radius);
  border-end-start-radius:   var(--field-radius);
}
.field-row > :last-child {
  border-start-end-radius: var(--field-radius);
  border-end-end-radius:   var(--field-radius);
}
/* Collapse the doubled border between neighbors. */
.field-row > * + * {
  margin-inline-start: -1px;
}
.field-row > .field {
  flex:            1;
  min-inline-size: 0;
}
/* Lift the focused control so its ring is not clipped by its neighbor. */
.field-row > .field:focus,
.field-row > .btn:focus-visible {
  position: relative;
  z-index:  1;
}

.field-addon {
  display:     inline-flex;
  align-items: center;
  padding-inline: var(--space-lg);
  background:  var(--surface-sunken);
  border:      var(--border-width) solid var(--rule-strong);
  color:       var(--ink-soft);
  font-family: var(--font-primary);
  font-size:   var(--text-md);
  white-space: nowrap;
}
