/* SLASHED — optional/forms.css
   @layer slashed.forms
   Classless form controls: text inputs, selects, textareas, checks/radios, fieldsets, labels.
   Values resolve through core and optional component tokens. */

@layer slashed.forms {

  /* Shared base for text-like inputs, select, textarea */

  input:where(
    [type="text"], [type="email"], [type="password"], [type="url"],
    [type="tel"], [type="number"], [type="search"], [type="date"],
    [type="datetime-local"], [type="month"], [type="week"],
    [type="time"], :not([type])
  ),
  select,
  textarea {

    appearance: none;

    display: block;
    inline-size: 100%;
    /* Field metrics resolve through the component-tier field knobs first, then
       the core rhythm knob, then the literal — so overriding any of them retunes
       fields without touching global spacing/radius. Every fallback equals the
       shipped default, so the default render is unchanged. --sf-field-padding-*
       and --sf-field-radius live in optional/tokens.components.css (present in
       the -components/full bundles); --sf-field-block is the core-tier fallback
       so the knob still works in the forms-only bundles. */
    padding-block: var(--sf-field-padding-block, var(--sf-field-block, var(--sf-space-xs)));
    padding-inline: var(--sf-field-padding-inline, var(--sf-space-s));
    font-size: var(--sf-text-m);
    line-height: var(--sf-leading-normal);
    color: var(--sf-color-text);
    background-color: var(--sf-color-surface);
    border: var(--sf-border-width-1) solid var(--sf-field-border-color, var(--sf-color-border));
    border-radius: var(--sf-field-radius, var(--sf-radius-m));
    transition: var(--sf-transition-form-field);
  }

  /* Focus */
  input:where(
    [type="text"], [type="email"], [type="password"], [type="url"],
    [type="tel"], [type="number"], [type="search"], [type="date"],
    [type="datetime-local"], [type="month"], [type="week"],
    [type="time"], :not([type])
  ):focus-visible,
  select:focus-visible,
  textarea:focus-visible {
    border-color: var(--sf-color-border--focus);
    outline: var(--sf-focus-ring-width) var(--sf-focus-ring-style, solid) var(--sf-color-border--focus);
    outline-offset: var(--sf-focus-ring-offset);
  }

  /* Disabled */
  input:disabled,
  select:disabled,
  textarea:disabled {
    background-color: var(--sf-color-bg--disabled);
    color: var(--sf-color-text--disabled);
    opacity: var(--sf-opacity-disabled);
    cursor: not-allowed;
  }

  /* Placeholder */
  input::placeholder,
  textarea::placeholder {
    color: var(--sf-color-text--placeholder);
    opacity: 1;
  }

  /* Autofill: strips Safari's own dark-mode autofill background; Chromium/Firefox honour
     the CSS background without this, but WebKit doesn't. */
  /* stylelint-disable selector-pseudo-class-no-unknown */
  input:-webkit-autofill {
    box-shadow: inset 0 0 0 1000px var(--sf-color-surface);
    -webkit-text-fill-color: var(--sf-color-text);
    caret-color: var(--sf-color-text);
    border-color: var(--sf-field-border-color, var(--sf-color-border));
  }
  input:autofill {
    box-shadow: inset 0 0 0 1000px var(--sf-color-surface);
    -webkit-text-fill-color: var(--sf-color-text);
    caret-color: var(--sf-color-text);
    border-color: var(--sf-field-border-color, var(--sf-color-border));
  }
  /* stylelint-enable selector-pseudo-class-no-unknown */

  /* Opt-in native validation feedback. Unconditional :user-invalid/:user-valid
     styling was removed in 0.8.0 (see docs/migration.md): it fires on simple
     focus+blur, so a still-empty required field could be marked invalid mid
     multi-field form-fill, before any submit was attempted — the pattern
     Bootstrap's own .was-validated gate exists to avoid. .sf-live-validate is
     that same gate: put it on a <form> or <fieldset> to scope the pivot to
     that subtree, so it only lights up on a real submit attempt (or explicit
     interaction) instead of applying everywhere by default.

     Safe to combine with manual validation: .sf-is-invalid/.sf-is-valid
     (core/states.css, @layer slashed.states) always win over the rules below
     regardless of selector specificity, because slashed.states is declared
     AFTER slashed.forms in the layer order (core/layers.css) — cascade layer
     order beats specificity. A field you've manually marked .sf-is-invalid
     (e.g. a server-side error) can't be silently un-coloured by these rules
     even if the browser considers it natively valid. */
  .sf-live-validate input:user-invalid,
  .sf-live-validate select:user-invalid,
  .sf-live-validate textarea:user-invalid {
    --sf-field-border-color: var(--sf-color-danger);
  }

  .sf-live-validate input:user-valid,
  .sf-live-validate select:user-valid,
  .sf-live-validate textarea:user-valid {
    --sf-field-border-color: var(--sf-color-success);
  }

  /* Numeric inputs */
  input[type="number"] {
    font-variant-numeric: var(--sf-font-numeric, tabular-nums);
  }

  /* Textarea specifics */
  textarea {
    min-block-size: 6rem;
    resize:         vertical;
  }

  @supports (field-sizing: content) {
    textarea {
      field-sizing: content;
    }
  }

  /* Select: chevron uses FieldText system color — custom properties don't propagate
     into data-URI SVG backgrounds. */
  select {
    padding-inline-end: calc(var(--sf-space-s) + 1.5em);
  }

  select:not([multiple], [size]) {
    background-repeat: no-repeat;
    background-position: right var(--sf-space-s) center;
    background-size: 1em;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='none' stroke='FieldText' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' d='M2.5 4.5L6 8l3.5-3.5'/%3E%3C/svg%3E");
  }

  :dir(rtl) select:not([multiple], [size]) {
    background-position: left var(--sf-space-s) center;
  }

  /* Button / submit / reset. Scoped to :where(form, fieldset) so a bare
     <button> or <input type="submit"/"reset"/"button"> used elsewhere on
     the page (a page-builder's hamburger toggle, a modal close control, a
     third-party widget) is left alone — only controls living inside an
     actual form get the classless treatment. */
  :where(form, fieldset) button:not([class*="sf-"]),
  :where(form, fieldset) input[type="submit"]:not([class*="sf-"]),
  :where(form, fieldset) input[type="reset"]:not([class*="sf-"]),
  :where(form, fieldset) input[type="button"]:not([class*="sf-"]) {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--sf-space-xs);
    padding-block: var(--sf-space-xs);
    padding-inline: var(--sf-space-m);
    font-size: var(--sf-text-m);
    font-weight: var(--sf-font-weight-heading);
    line-height: var(--sf-leading-normal);
    color: var(--sf-color-text--on-action);
    background-color: var(--sf-color-action);
    border: var(--sf-border-width-1) solid transparent;
    border-radius: var(--sf-radius-m);
    cursor: pointer;
    transition: var(--sf-transition-colors);
    text-decoration: none;
  }

  :where(form, fieldset) button:not([class*="sf-"]):hover,
  :where(form, fieldset) input[type="submit"]:not([class*="sf-"]):hover,
  :where(form, fieldset) input[type="reset"]:not([class*="sf-"]):hover,
  :where(form, fieldset) input[type="button"]:not([class*="sf-"]):hover {

    background-color: var(--sf-color-action--hover, var(--sf-color-action));
  }

  :where(form, fieldset) button:not([class*="sf-"]):focus-visible,
  :where(form, fieldset) input[type="submit"]:not([class*="sf-"]):focus-visible,
  :where(form, fieldset) input[type="reset"]:not([class*="sf-"]):focus-visible,
  :where(form, fieldset) input[type="button"]:not([class*="sf-"]):focus-visible {
    outline: var(--sf-focus-ring-width) var(--sf-focus-ring-style, solid) var(--sf-color-border--focus);
    outline-offset: var(--sf-focus-ring-offset);
  }

  :where(form, fieldset) button:not([class*="sf-"]):disabled,
  :where(form, fieldset) input[type="submit"]:not([class*="sf-"]):disabled,
  :where(form, fieldset) input[type="reset"]:not([class*="sf-"]):disabled,
  :where(form, fieldset) input[type="button"]:not([class*="sf-"]):disabled {
    opacity: var(--sf-opacity-disabled);
    cursor:  not-allowed;

  }

  /* Checkbox & radio */
  input[type="checkbox"],
  input[type="radio"] {
    inline-size:    1.125em;
    block-size:     1.125em;
    accent-color:   var(--sf-color-action);
    cursor:         pointer;
    vertical-align: middle;
  }

  /* File input */
  input[type="file"] {
    cursor: pointer;
  }
  input[type="file"]::file-selector-button {
    appearance: none;
    margin-inline-end: var(--sf-space-s);
    padding-block: var(--sf-space-xs);
    padding-inline: var(--sf-space-m);
    font-weight: var(--sf-font-weight-heading);
    color: var(--sf-color-text--on-action);
    background-color: var(--sf-color-action);
    border: var(--sf-border-width-1) solid transparent;
    border-radius: var(--sf-radius-m);
    cursor: pointer;
    transition: var(--sf-transition-colors);
  }
  input[type="file"]::file-selector-button:hover {
    background-color: var(--sf-color-action--hover, var(--sf-color-action));
  }

  /* Range */
  input[type="range"] {
    appearance: none;
    inline-size: 100%;
    background: transparent;
    cursor: pointer;
  }
  input[type="range"]::-webkit-slider-runnable-track {
    block-size: var(--sf-border-width-3, 0.25rem);
    background-color: var(--sf-color-border);
    border-radius: var(--sf-radius-full);
  }
  input[type="range"]::-moz-range-track {
    block-size: var(--sf-border-width-3, 0.25rem);
    background-color: var(--sf-color-border);
    border-radius: var(--sf-radius-full);
  }
  input[type="range"]::-webkit-slider-thumb {
    appearance: none;
    inline-size: 1em;
    block-size: 1em;
    margin-block-start: calc((var(--sf-border-width-3, 0.25rem) - 1em) / 2);
    background-color: var(--sf-color-action);
    border-radius: var(--sf-radius-full);
  }
  input[type="range"]::-moz-range-thumb {
    inline-size: 1em;
    block-size: 1em;
    background-color: var(--sf-color-action);
    border: none;
    border-radius: var(--sf-radius-full);
  }
  input[type="range"]:focus-visible {
    outline: var(--sf-focus-ring-width) var(--sf-focus-ring-style, solid) var(--sf-color-border--focus);
    outline-offset: var(--sf-focus-ring-offset);
  }

  /* Fieldset & legend */
  fieldset {
    border: var(--sf-border-width-1) solid var(--sf-color-border--subtle);
    border-radius: var(--sf-radius-m);
    padding: var(--sf-space-m);
  }

  legend {
    font-weight: var(--sf-font-weight-heading);
    padding-inline: var(--sf-space-xs);
  }

  /* Label */
  label {
    display: block;
    font-weight: var(--sf-font-weight-heading);
    margin-block-end: var(--sf-space-xs);
    color: var(--sf-field-text-color, inherit);
  }

  label:has(:required)::after,
  label:has(+ :required)::after,
  label:has(+ * :required)::after {
    content: var(--sf-field-required-marker, " *");
    color: var(--sf-color-danger);
  }

}
