/* Safari 17.x bug: `:scope[attr]:hover` and `:scope:not(...) [descendant]:hover`
   inside `@scope` don't match the scope root. Plain selectors outside work.
   See docs/BROWSER-COMPAT.md §3a. */
input-ui[variant="ghost"]:hover {
  --input-bg: var(--a-bg-muted);
}
input-ui:not([disabled]) [slot="field"]:hover {
  background: var(--input-bg-hover);
  border-color: var(--input-border-hover);
  color: var(--input-fg-hover);
}
input-ui:not([disabled]) [slot="field"]:hover [slot="prefix"],
input-ui:not([disabled]) [slot="field"]:hover [slot="suffix"] {
  color: var(--input-affix-fg-hover);
}

@scope (input-ui) {
  :where(:scope) {
    /* ── Tokens (wired to --a-ui-*) ── */
    --input-bg:              var(--a-ui-bg);
    --input-fg:              var(--a-ui-text);
    --input-border:          var(--a-ui-border);
    --input-border-hover:    var(--a-ui-border-hover);
    --input-focus-ring:      var(--a-focus-ring);
    --input-focus-ring-invalid: var(--a-focus-ring-invalid);
    --input-radius:          var(--a-radius);
    --input-height:          var(--a-size);
    --input-px:              var(--a-ui-px);
    --input-font-size:       var(--a-ui-size);
    --input-font-family:     var(--a-font-family-ui);
    --input-placeholder-fg:  var(--a-ui-text-placeholder);
    --input-affix-fg:        var(--a-ui-text-placeholder);
    --input-field-gap:       var(--a-space-1);
    --input-label-min-width: 8ch;

    /* ── Transitions ── */
    --input-duration:        var(--a-duration-fast);
    --input-easing:          var(--a-easing);

    /* ── State: hover/focus ── */
    --input-bg-hover:        var(--a-ui-bg-hover);
    --input-fg-hover:        var(--a-ui-text-hover);
    --input-affix-fg-hover:  var(--a-ui-text-subtle);
    --input-fg-focus:        var(--a-ui-text-active);

    /* ── State: disabled ── */
    --input-bg-disabled:     var(--a-ui-bg-disabled);
    --input-fg-disabled:     var(--a-ui-text-disabled);
    text-align: start;  /* §text-align-reset — blocks inheritance from centered ancestors */
}

  :scope {
    /* ── Base ── */
    box-sizing: border-box;
    display: block;
  }

  /* Inline label — sits inside [slot="field"] as a leading caption,
     between [slot="prefix"] and [slot="text"]. Dim by default; shares
     the input chrome border. For stacked label / hint / error, wrap
     with field-ui.

     min-width reserves a label column so a short label (e.g. "PIN")
     doesn't sit flush against the value text, and the value start aligns
     down a stack of inputs. flex-shrink: 0 keeps it from collapsing; a
     label wider than the floor grows past it. */
  [slot="label"] {
    flex-shrink: 0;
    min-width: var(--input-label-min-width);
    color: var(--input-affix-fg);
    font-size: var(--input-font-size);
    user-select: none;
    pointer-events: none;
  }

  /* Field container */
  [slot="field"] {
    display: flex;
    align-items: center;
    gap: var(--input-field-gap);
    min-height: var(--input-height);
    padding: 0 var(--input-px);
    border: 1px solid var(--input-border);
    border-radius: var(--input-radius);
    background: var(--input-bg);
    color: var(--input-fg);
    font: inherit;
    /* font-family floor — see segment.css rationale. */
    font-family: var(--input-font-family);
    font-size: var(--input-font-size);
    /* line-height: 1.4 (not 1) so descender-bearing glyphs (g, j, p, q, y)
       have room inside [slot="text"]'s line box. With line-height: 1 the
       line box equals the em-square and descenders extend below it; the
       overflow: hidden on [slot="text"] then clips them. The min-height
       still controls overall chrome height — align-items: center keeps the
       baseline centered regardless of line-height. */
    line-height: 1.4;
    cursor: text;
    /* Cover every property the hover / focus / invalid states change so
       the field doesn't half-snap (border slides, but bg/colour/ring snap). */
    transition:
      background  var(--input-duration) var(--input-easing),
      border-color var(--input-duration) var(--input-easing),
      color       var(--input-duration) var(--input-easing),
      box-shadow  var(--input-duration) var(--input-easing);
  }
  /* hover rules moved outside @scope — see Safari 17.x bug note at top. */
  :scope:not([disabled]):focus-within [slot="field"] {
    /* Canonical ring — consumes the L3 --input-focus-ring token
       which aliases --a-focus-ring. Border stays stable; the ring
       is the focus affordance (WCAG 2.2 SC 2.4.11/2.4.13). */
    box-shadow: var(--input-focus-ring);
    color: var(--input-fg-focus);
  }
  :scope[aria-invalid="true"]:not([disabled]):focus-within [slot="field"],
  :scope[error]:not([disabled]):focus-within [slot="field"] {
    box-shadow: var(--input-focus-ring-invalid);
  }

  /* Text (contenteditable span) */
  [slot="text"] {
    flex: 1;
    min-width: 0;
    outline: none;
    white-space: nowrap;
    overflow: hidden;
    /* Positioning context for the [data-empty]::before placeholder
       pseudo, which is taken out of inline flow so the caret renders
       at the actual content-start (not after the pseudo box). */
    position: relative;
  }

  /* Text (native input — password only) */
  input[slot="text"] {
    border: none;
    background: transparent;
    color: inherit;
    font: inherit;
    font-size: inherit;
    padding: 0;
    height: auto;
  }

  input[slot="text"]::placeholder {
    color: var(--input-placeholder-fg);
  }

  /* Placeholder (contenteditable only).
     Out-of-flow positioning is load-bearing — an in-flow ::before with
     `content: attr(...)` puts the pseudo box INLINE before the empty
     text node, which means the caret-at-position-0 visually renders to
     the RIGHT of the placeholder text (after the user types and deletes).
     `position: absolute; inset: 0; padding: inherit` makes the pseudo
     fill the host's content-box without occupying any inline-flow space,
     so the caret renders at the actual content-start where it belongs. */
  span[slot="text"][data-empty]::before {
    content: attr(data-placeholder);
    color: var(--input-placeholder-fg);
    pointer-events: none;
    position: absolute;
    inset: 0;
    padding: inherit;
  }

  /* ── Number mode (type="number") ──
     Right-aligned digits with tabular-nums so rapid stepping doesn't
     jitter the value horizontally. The stepper column is positioned
     absolutely against the field's inline-end edge so it NEVER affects
     the field's flex-sized height — number-mode inputs share the same
     24/30/36px (sm/md/lg) baseline as text/email/password/etc. */
  [data-number] [slot="text"] {
    text-align: end;
    font-variant-numeric: tabular-nums;
    font-weight: var(--a-weight-medium, 500);
    /* Reserve space for the absolutely-positioned controls column so the
       value never collides with the stepper buttons. */
    padding-inline-end: var(--input-controls-width, calc(var(--input-height) * 0.7));
  }

  /* Suffix sits flush after the value in number mode (no auto margin so
     the value+suffix pair stays right-aligned together). */
  [data-number] [slot="suffix"] {
    margin-inline-start: 0;
    /* Reserve space for the absolutely-positioned controls column so the
       suffix never collides with the stepper buttons. The padding moves
       from `[slot="text"]` to `[slot="suffix"]` when a suffix is present
       — only one element needs the reservation since they're adjacent. */
    margin-inline-end: var(--input-controls-width, calc(var(--input-height) * 0.7));
  }
  [data-number]:has([slot="suffix"]) [slot="text"] {
    padding-inline-end: 0;
  }

  [data-number] {
    position: relative;
  }

  [slot="controls"] {
    position: absolute;
    inset-block: 0;
    inset-inline-end: 0;
    display: grid;
    grid-template-rows: 1fr 1fr;
    border-inline-start: 1px solid var(--input-border);
    width: var(--input-controls-width, calc(var(--input-height) * 0.7));
    user-select: none;
    overflow: hidden;
  }

  [data-number] [slot="controls"] button-ui {
    /* Defeat button-ui's intrinsic min-height (driven by --button-height) so
       its content can't push past half the column height. Padding + border
       are zeroed; the divider between the two buttons comes from the
       :first-child border-bottom rule below. Override button-ui's
       `display: inline-flex` to `flex` so `width: 100%` fills the grid
       track instead of collapsing to content. */
    display: flex;
    --button-height: 0;
    --button-radius: 0;
    --button-bg: transparent;
    --button-fg: var(--input-affix-fg);
    --button-px: 0;
    min-width: 0;
    min-height: 0;
    width: 100%;
    height: 100%;
    border: 0;
    padding: 0;
  }
  /* Override icon-ui's self-declared --icon-size (which is `calc(1em +
     0.125rem)` by default — the +0.125rem overshoot would push the icon
     past the half-column cell). Targeting icon-ui directly is required
     because its own `:where(:scope)` declaration of --icon-size wins over
     any value inherited from its parent button-ui. Tying it to
     --input-height keeps the caret proportional across sm/md/lg. */
  [data-number] [slot="controls"] icon-ui {
    --icon-size: calc(var(--input-height) * 0.4);
  }
  [data-number] [slot="controls"] button-ui:hover {
    --button-bg: var(--a-ui-bg-hover);
    --button-fg: var(--a-ui-text);
  }
  [data-number] [slot="controls"] button-ui[disabled] {
    --button-fg: var(--a-ui-text-disabled);
    pointer-events: none;
  }
  /* Field-level focus ring sits OUTSIDE the chrome and would clip the
     bottom-right corner of the controls column. Round the corners of the
     buttons that touch the chrome edge so the focus ring follows the
     field radius cleanly. The divider between the two buttons is the
     inline-start border on the column + the bottom-border on the upper
     button. */
  [data-number] [slot="controls"] button-ui:first-child {
    border-bottom: 1px solid var(--input-border);
    border-start-end-radius: calc(var(--input-radius) - 1px);
  }
  [data-number] [slot="controls"] button-ui:last-child {
    border-end-end-radius: calc(var(--input-radius) - 1px);
  }

  /* Raw mode strips the chrome — also strip the controls column's
     border + corner radii. */
  :scope[raw] [slot="controls"] {
    margin-inline-end: 0;
    border-inline-start: none;
  }
  :scope[raw] [data-number] [slot="controls"] button-ui:first-child,
  :scope[raw] [data-number] [slot="controls"] button-ui:last-child {
    border-bottom: none;
    border-radius: 0;
  }

  /* Prefix + Suffix — inline-flex so icon-ui (or any non-text affix
     content) centers vertically within the slot wrapper. Without
     this, an icon inside a default <span slot="prefix"> sits at the
     baseline of the field's 1.4 line-box and renders visually below
     the field's center. With inline-flex + align-items: center the
     icon centers in the slot box, which is itself centered in the
     field via the field's align-items: center. */
  [slot="prefix"],
  [slot="suffix"] {
    display: inline-flex;
    align-items: center;
    flex-shrink: 0;
    color: var(--input-affix-fg);
    font-size: var(--input-font-size);
    line-height: 1;
    user-select: none;
    pointer-events: none;
  }

  [slot="suffix"] {
    margin-inline-start: auto;
  }

  /* §199 (v0.5.7) — Leading + trailing affordance slots inside the field.
     Consumer authors `<button-ui slot="leading|trailing">` as a direct
     child of <input-ui>; input.class.js#installAffordances moves it into
     [slot="field"] at the right insertion point on connected(). CSS
     normalizes the chrome here.

     The yaml declared these slots since v1 ("sized to --content-height,
     collapses text inline padding when present") but no shell rule ever
     wired them — the canonical schema-vs-impl gap that motivated audit
     slot 19 (§192 v0.5.6). §199 closes the gap for input-ui specifically. */

  [slot="field"] > [slot="leading"],
  [slot="field"] > [slot="trailing"] {
    flex-shrink: 0;
    /* Vertically CENTER the affordance in the chrome — do not `stretch`.
       Stretch forces the slot box to the full chrome height; for a button-ui
       child that overrode its own `--button-height` (chrome − 4px), and for a
       fixed-height affordance like <kbd-ui> (definite `height`) stretch can't
       grow the box so it pins to flex-start (top) instead — the ⌘K hint sat
       ~4px high (bug-60). `center` lets each child keep its own token height
       and sit on the field's vertical center. */
    align-self: center;
    display: inline-flex;
    align-items: center;
    /* Inline padding moves from [slot="text"] (handled by the field's px)
       to the slot wrapper, so the button-ui sits flush with the field
       chrome edge instead of inheriting the field's px gap. Authors who
       want a gap between value and trailing affordance use [slot="suffix"]
       for the text — the auto-margin on suffix pushes everything after it
       to the inline-end edge naturally. */
  }

  /* Default sizing for `<button-ui>` children of the affordance slots.
     Token-driven so consumers can override via standard --button-* hooks.
     Without these defaults, a vanilla `<button-ui slot="trailing" icon="...">`
     would render at button-ui's default --button-height (40px md) and
     blow out the input chrome. We bind to the field's content height
     instead so the button visually matches the input's intrinsic size. */
  [slot="field"] > [slot="leading"] button-ui,
  [slot="field"] > [slot="trailing"] button-ui {
    --button-height: calc(var(--input-height) - 4px);
    --button-bg: transparent;
    --button-border: transparent;
    --button-fg: var(--input-affix-fg);
    --button-px: var(--a-space-1);
  }

  [slot="field"] > [slot="leading"] button-ui:hover,
  [slot="field"] > [slot="trailing"] button-ui:hover {
    --button-bg: var(--a-ui-bg-hover);
    --button-fg: var(--a-fg);
  }

  /* When a trailing affordance is present in number mode, reserve room
     for the stepper column so it doesn't overlap. (controls is
     absolutely positioned at inset-inline-end: 0; trailing sits in the
     flex flow.) Same pattern as [slot="suffix"] in number mode. */
  [data-number]:has(> [slot="trailing"]) > [slot="trailing"] {
    margin-inline-end: var(--input-controls-width, calc(var(--input-height) * 0.7));
  }

  /* Disabled */
  :scope[disabled] [slot="field"] {
    background: var(--input-bg-disabled);
    color: var(--input-fg-disabled);
    cursor: not-allowed;
  }

  /* Raw mode */
  :scope[raw] [slot="field"] {
    border: none;
    background: transparent;
    padding: 0;
    border-radius: 0;
    min-height: auto;
  }

  /* Size handled by universal [size] attribute system. */

  /* Ghost variant */
  :scope[variant="ghost"] {
    --input-bg: transparent;
    --input-border: transparent;
    --input-border-hover: transparent;
  }
  /* :scope[variant="ghost"]:hover moved outside @scope — see Safari
     17.x bug note at top of file. */
}
