/*
 * Forms — text inputs, labels, helper/error text, fieldsets.
 *
 * The single canonical form pattern for the whole app. Every form in
 * Finances_app should use these classes so inputs look, feel, and
 * respond identically across surfaces. If a form needs a variant the
 * pattern doesn't support, add the variant here rather than forking
 * styles in the calling template.
 *
 * Structural convention:
 *
 *   <div class="form-field">
 *     <div class="form-field__label-row">
 *       <label class="form-field__label" for="...">Email</label>
 *       <a class="form-field__inline-link">Forgot?</a>  (optional)
 *     </div>
 *     <input class="form-field__input" …>
 *     <p class="form-field__hint">optional helper text</p>
 *     <p class="form-field__error">optional error text</p>
 *   </div>
 *
 * States on the input: default, :hover, :focus-visible, :disabled,
 * [aria-invalid="true"] (error). Focus ring matches buttons for
 * consistency — same ring color, same offset.
 */

@layer components {
  .form {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
  }

  .form-field {
    /* Component-local token — colour for inline action icons (eye
       toggle, clear button) that sit inside `.form-field__input-wrap`.
       Slate-600 picks up the quiet-but-readable shade originally
       chosen for these affordances; switching to a palette pull lets
       a future palette tune-up propagate. */
    --color-icon-muted: var(--color-slate-600);

    /* Hairline border — universal 1px border-width; no system
       border-width scale yet. */
    --form-border-size: 1px;

    /* Soft focus halo width — input focus uses a 3px halo at 20%
       opacity, distinct from the button's 2-step ring; component-
       local because there's no system token for this scale. */
    --form-focus-halo-size: 3px;

    /* Input-action button dimensions + padding adjustments. Sized to
       sit cleanly inside the input row without crowding the text. */
    --form-action-size:        2rem;
    --form-action-svg-size:    1.125rem;
    --form-action-wrap-pad-right: 2.75rem;

    display: flex;
    flex-direction: column;
    gap: var(--space-1-5);
  }

  /*
   * Restore the browser's default `[hidden] { display: none }` for
   * .form-field — the `display: flex` rule above otherwise wins
   * over the user-agent style and a `<div class="form-field"
   * hidden>` stays visible. Stimulus controllers (e.g. the
   * approver-picker's count field) toggle this attribute to show /
   * hide conditional inputs; the rule below makes that
   * toggle actually hide the field.
   */
  .form-field[hidden] {
    display: none;
  }

  .form-field__label-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-3);
  }

  .form-field__label {
    font-size: var(--text-13);
    font-weight: 500;
    color: var(--color-text-heading);
    line-height: var(--leading-tight);
  }

  .form-field__inline-link {
    font-size: var(--text-xs);
    /* color + hover inherit from base `a` rule (primary tokens). */
  }

  .form-field__input {
    /* Define these here (not only on the .form-field wrapper) so a .form-field__input used WITHOUT a
       wrapper — e.g. a bare <select> in a card — still resolves them. An undefined var() makes the
       whole `border` / `box-shadow` invalid at computed-value time and it's dropped (that's why bare
       dropdowns had no border and no focus halo). */
    --form-border-size: 1px;
    --form-focus-halo-size: 3px;
    -webkit-appearance: none; /* selects need the prefixes to drop native chrome and honour the CSS border */
    -moz-appearance: none;
    appearance: none;
    width: 100%;
    box-sizing: border-box;
    min-height: var(--space-10);
    padding: 0 var(--space-3);
    /* Visible slate hairline on every field. (The real reason dropdowns looked borderless wasn't the
       shade — it was the undefined token above dropping the border entirely.) Indigo halo on :focus. */
    border: var(--form-border-size) solid var(--color-slate-400);
    border-radius: var(--radius-md);
    background: var(--color-white);
    color: var(--color-slate-900);
    font: inherit;
    font-size: var(--text-15);
    line-height: var(--leading-snug);
    transition: border-color var(--duration-base) var(--ease-out),
                box-shadow var(--duration-base) var(--ease-out);
  }

  .form-field__input::placeholder {
    color: var(--color-slate-400);
  }

  .form-field__input:hover {
    border-color: var(--color-slate-500);
  }

  /*
   * Native <select> — `appearance: none` (above) strips the browser's dropdown
   * arrow, so a select looks identical to a text input (white-in-white). Paint a
   * chevron-up-down (heroicon, slate stroke) on the right so it reads as a
   * dropdown, and reserve room for it. Multi-selects are list boxes, not
   * dropdowns, so they keep the plain look.
   */
  /* Explicit border + focus on selects too — some engines drop the inherited ones once the native
     control is suppressed, which left dropdowns borderless with no focus halo. */
  select.form-field__input:not([multiple]) {
    padding-right: calc(var(--space-3) + 1.5rem);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke-width='1.5' stroke='%2364748b'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M8.25 15 12 18.75 15.75 15m-7.5-6L12 5.25 15.75 9'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right var(--space-3) center;
    background-size: 1.25rem;
  }

  .form-field__input:focus-visible,
  .form-field__input:focus {
    outline: none;
    border-color: var(--color-primary);
    /* color-mix (widely supported) rather than the newer oklch(from …) relative syntax, so the
       indigo halo renders on every focusable field — including native <select>s. */
    box-shadow: 0 0 0 var(--form-focus-halo-size) color-mix(in oklab, var(--color-primary) 20%, transparent);
  }

  .form-field__input:disabled {
    background: var(--color-slate-50);
    color: var(--color-slate-500);
    cursor: not-allowed;
  }

  .form-field__input[aria-invalid="true"] {
    border-color: var(--color-danger);
  }

  .form-field__input[aria-invalid="true"]:focus-visible {
    box-shadow: 0 0 0 var(--form-focus-halo-size) color-mix(in oklab, var(--color-danger) 20%, transparent);
  }

  /* Input with trailing action (eye toggle, clear button, etc.) —
     wraps the input so an icon-button can sit over its right edge. */
  .form-field__input-wrap {
    position: relative;
  }

  .form-field__input-wrap .form-field__input {
    padding-right: var(--form-action-wrap-pad-right);
  }

  .form-field__input-action {
    position: absolute;
    top: 50%;
    right: var(--space-1-5);
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--form-action-size);
    height: var(--form-action-size);
    padding: 0;
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--color-icon-muted);
    cursor: pointer;
    transition: background-color var(--duration-base) var(--ease-out),
                color var(--duration-base) var(--ease-out);
  }

  .form-field__input-action:hover {
    color: var(--color-text-heading);
  }

  .form-field__input-action:focus-visible {
    outline: var(--focus-ring-size) solid var(--focus-ring-color);
    outline-offset: var(--focus-ring-offset);
  }

  .form-field__input-action svg {
    width: var(--form-action-svg-size);
    height: var(--form-action-svg-size);
  }

  /* Force the HTML `hidden` attribute on SVG — some browsers ignore
     it because the attribute is defined in HTML, not SVG, namespace. */
  .form-field__input-action svg[hidden] {
    display: none;
  }

  /*
   * Textarea — the multi-line equivalent of `.form-field__input`.
   *
   * Shares every state — :hover, :focus, :disabled, [aria-invalid] —
   * because all of those live on the input class, and we apply that
   * class to the textarea too. The textarea-specific class only adds
   * the dimensions and font that don't make sense on a single-line
   * input: symmetric vertical padding, line-height for multi-line
   * flow, and a resize handle that's vertical-only so the user can
   * grow the field without breaking the column.
   *
   * Usage:
   *
   *   <textarea class="form-field__input form-field__textarea" rows="6">
   *
   * Monospace variant for character-grid surfaces (Finn playbook slot
   * editor; future structured-prompt or template editors):
   *
   *   <textarea class="form-field__input form-field__textarea
   *                    form-field__textarea--monospace" rows="10">
   *
   * `min-height: auto` so the `rows` attribute drives the resting
   * height — the textarea grows / shrinks with content rather than
   * being clamped to the input min-height. The width is `100%` via
   * the inherited `.form-field__input` rule.
   */
  .form-field__textarea {
    /* Override `.form-field__input`'s `min-height: var(--space-10)` so
       the `rows` attribute decides the resting height. */
    --form-field-textarea-min-height: auto;

    /* Symmetric vertical padding — `.form-field__input` uses
       `padding: 0 var(--space-3)` and relies on `min-height` +
       inline-flex centering for vertical air. Textareas can't centre
       multi-line content, so they need real top/bottom padding. */
    --form-field-textarea-padding-block: var(--space-2);

    /* Line-height tuned for multi-line reading. Matches
       `--leading-snug` from the typography ramp. */
    --form-field-textarea-line-height: var(--leading-snug);

    /* Resize handle — vertical only. Horizontal resize would let the
       textarea push past the form column. */
    --form-field-textarea-resize: vertical;

    /* Font family — `inherit` by default (Inter, like every other
       form input). The `--monospace` variant overrides to the system
       monospace stack. */
    --form-field-textarea-font: inherit;

    min-height: var(--form-field-textarea-min-height);
    padding: var(--form-field-textarea-padding-block) var(--space-3);
    line-height: var(--form-field-textarea-line-height);
    resize: var(--form-field-textarea-resize);
    font-family: var(--form-field-textarea-font);
  }

  /* Monospace variant — character-grid surfaces where column
     alignment matters (Finn playbook slots editor today). Reads the
     `--font-family-mono` system token so a future monospace-stack
     change propagates to every consumer in one move. */
  .form-field__textarea--monospace {
    --form-field-textarea-font: var(--font-family-mono);
  }

  .form-field__hint {
    margin: 0;
    font-size: var(--text-xs);
    /* color inherits from base `html` rule (body token). */
  }

  .form-field__error {
    margin: 0;
    font-size: var(--text-xs);
    color: var(--color-danger);
  }
}
