/* ==========================================================
   IROZON DESIGN SYSTEM — Input / Textarea (canonical, v1)
   Public API: <input class="iz-input" type="text|email|password|search">
   and <textarea class="iz-textarea">. Native elements, native
   semantics — this file only draws the Irozon surface around them.
   State is read from disabled / readonly / aria-invalid, never a
   visual state class. Select's own chrome lives in select.css but
   shares this base via the same grouped selector.

   Plain comma-separated selectors, not :where(...) — a :where() list
   carries zero specificity, so it loses outright to any consumer's own
   non-zero-specificity element-type reset (e.g. Tailwind Preflight's
   `button, input, optgroup, select, textarea { padding: 0; ... }`),
   regardless of stylesheet order. That's exactly what silently zeroed
   this file's padding-inline/padding-block in every real consumer
   (irozon.se, Irozon Invoice) while border/background/font-size kept
   working — those happened to still win on source order against the
   zero-specificity universal-selector reset (`*, ::before, ::after`),
   but padding was up against a *non-zero*-specificity reset that
   :where()'s zero specificity can never out-rank. A plain selector
   list gives this rule real (0,1,0)-class specificity per selector,
   so it reliably wins against element-type resets in any consumer,
   the way a component's own geometry should.
   ========================================================== */

.iz-input,
.iz-textarea,
.iz-select {
  display: block;
  inline-size: 100%;
  min-block-size: 44px;
  padding-inline: 14px;
  padding-block: 10px;
  border-radius: var(--r-sm);
  border: 1px solid var(--color-border-strong);
  background: var(--color-surface);
  color: var(--color-text-primary);
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  line-height: 1.4;
  transition:
    border-color var(--motion-duration-fast) var(--motion-ease-standard),
    background-color var(--motion-duration-fast) var(--motion-ease-standard),
    box-shadow var(--motion-duration-fast) var(--motion-ease-standard);
}

.iz-input::placeholder,
.iz-textarea::placeholder {
  color: var(--color-text-muted);
  opacity: 1;
}

/* Hover — a quiet border shift. No surface lift, no scale, no Green;
   a form control is not a button and shouldn't reward exploration the
   way one does. Explicitly excluded once focused (:not(:focus-visible))
   — without that, hover's higher selector specificity would win over
   the focus rule below and show its neutral border *underneath* the
   Green focus ring (the mouse is almost always still resting on a
   field right after clicking into it), reading as a dark border
   stacked with a Green halo instead of one Green focus system. */
.iz-input:hover:not(:disabled):not(:read-only):not(:focus-visible),
.iz-textarea:hover:not(:disabled):not(:read-only):not(:focus-visible),
.iz-select:hover:not(:disabled):not(:read-only):not(:focus-visible) {
  border-color: var(--color-text-secondary);
}

/* Focus — the one moment Green shows up: border and halo both Green,
   nothing else competing. box-shadow, not border-width, so nothing
   reflows. Ring size/opacity is intentionally lighter in light theme
   only (2px/20%) than dark (3px/22%, unchanged) — the same ring read
   as noticeably heavier against a light surface than a dark one. */
.iz-input:focus-visible,
.iz-textarea:focus-visible,
.iz-select:focus-visible {
  outline: none;
  border-color: var(--color-focus);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--color-focus) 20%, transparent);
}
:root[data-theme="dark"] .iz-input:focus-visible,
:root[data-theme="dark"] .iz-textarea:focus-visible,
:root[data-theme="dark"] .iz-select:focus-visible {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-focus) 22%, transparent);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .iz-input:focus-visible,
  :root:not([data-theme="light"]) .iz-textarea:focus-visible,
  :root:not([data-theme="light"]) .iz-select:focus-visible {
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-focus) 22%, transparent);
  }
}
@media (prefers-reduced-motion: reduce) {
  .iz-input,
  .iz-textarea,
  .iz-select {
    transition: none;
  }
}

/* Invalid — aria-invalid="true" is the single source of truth; no
   .is-error class. Pair with .iz-field__error in markup so the
   problem is never conveyed by color alone. */
.iz-input[aria-invalid="true"],
.iz-textarea[aria-invalid="true"],
.iz-select[aria-invalid="true"] {
  border-color: var(--color-error);
}
.iz-input[aria-invalid="true"]:focus-visible,
.iz-textarea[aria-invalid="true"]:focus-visible,
.iz-select[aria-invalid="true"]:focus-visible {
  border-color: var(--color-error);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-error) 22%, transparent);
}

/* Disabled — genuinely unavailable. Native :disabled already blocks
   interaction and removes it from the tab order; visually it recedes. */
.iz-input:disabled,
.iz-textarea:disabled,
.iz-select:disabled {
  background: var(--color-surface-subtle);
  border-color: var(--color-border);
  color: var(--color-text-muted);
  opacity: 0.7;
  cursor: not-allowed;
}

/* Read-only — the value is present and legible, just not editable.
   Deliberately not styled identically to disabled: text stays at full
   reading contrast, no "not-allowed" cursor, no opacity cut. (Select
   has no native readonly, so this only applies to input/textarea.) */
.iz-input:read-only:not(:disabled),
.iz-textarea:read-only:not(:disabled) {
  background: var(--color-surface-subtle);
  border-color: var(--color-border);
  color: var(--color-text-secondary);
}

/* Autofill — normalize the browser's own yellow/blue fill so it stays
   on-brand, without touching autofill's actual behavior. */
.iz-input:-webkit-autofill,
.iz-input:-webkit-autofill:hover,
.iz-input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--color-text-primary);
  -webkit-box-shadow: 0 0 0 1000px var(--color-surface) inset;
  transition: background-color 9999s ease-in-out 0s;
}

/* Search — normalize the native decorations that clash with our
   surface (iOS/WebKit's rounded pill, the built-in cancel button)
   without replacing the control itself. */
.iz-input[type="search"] {
  appearance: none;
  -webkit-appearance: none;
}
.iz-input[type="search"]::-webkit-search-cancel-button,
.iz-input[type="search"]::-webkit-search-decoration {
  -webkit-appearance: none;
}

/* Textarea — same surface, naturally variable height. Resizing stays
   on; only the direction is constrained so layout can't be broken
   sideways. */
.iz-textarea {
  min-block-size: 96px;
  resize: vertical;
}
