/* ═══════════════════════════════════════════════════════════════
   MODAL-UI — Centered dialog overlay using native <dialog>.

   <dialog> content stays in DOM tree → custom properties inherit
   normally → all rules live INSIDE @scope (modal-ui), parity with
   drawer-ui. See docs/specs/component-token-contract.md
   §"Top-layer rules — when to keep them inside @scope".
   ═══════════════════════════════════════════════════════════════ */

@scope (modal-ui) {
  :where(:scope) {
    --modal-width:          32rem;
    --modal-radius:         var(--a-radius-lg);
    --modal-bg:             var(--a-bg-subtle);
    --modal-border:         var(--a-border-subtle);
    --modal-shadow:         var(--a-shadow-lg);
    --modal-backdrop:       var(--a-scrim-dialog);
    --modal-duration:       var(--a-duration);
    --modal-easing:         var(--a-easing-out);
    --modal-heading-size:   var(--a-ui-lg);
    --modal-heading-weight: var(--a-weight-semibold);
    --modal-header-fg:      var(--a-fg);
    --modal-close-fg:       var(--a-fg-muted);
    --modal-close-hover:    var(--a-fg);
    --modal-pad-header:     var(--a-space-3);
    --modal-pad-body:       var(--a-space-4);
    --modal-pad-footer:     var(--a-space-3);
    --modal-font-family:    var(--a-font-family);
    --modal-footer-gap:     var(--a-space-2);
  }

  :scope {
    box-sizing: border-box;
    display: contents;
  }

  /* ── Size variants ── */
  :scope[size="sm"] { --modal-width: min(24rem, 90vw); }
  :scope[size="md"] { --modal-width: min(32rem, 90vw); }
  :scope[size="lg"] { --modal-width: min(48rem, 90vw); }

  /* ═══════ Closed ═══════ */
  :scope [slot="dialog"]:not([open]) { display: none; }

  /* ═══════ Full-viewport dialog shell ═══════ */
  :scope [slot="dialog"][open] {
    box-sizing: border-box;
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    max-width: none;
    max-height: none;
    margin: 0;
    padding: 0;
    border: none;
    background: transparent;
    overflow: clip;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  /* ═══════ Backdrop ═══════ */
  :scope [slot="dialog"]::backdrop {
    background: var(--modal-backdrop);
    opacity: 0;
    transition: opacity var(--modal-duration) var(--modal-easing);
  }
  :scope [slot="dialog"][data-open]::backdrop    { opacity: 1; }
  :scope [slot="dialog"][data-closing]::backdrop { opacity: 0; }

  /* ═══════ Content panel ═══════ */
  :scope [slot="dialog"] [slot="panel"] {
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    width: var(--modal-width);
    max-height: 85vh;
    background: var(--modal-bg);
    color: var(--modal-header-fg);
    font-family: var(--modal-font-family);
    border: 1px solid var(--modal-border);
    border-radius: var(--modal-radius);
    box-shadow: var(--modal-shadow);
    overflow: hidden;
    opacity: 0;
    transform: scale(0.95);
  }

  /* ═══════ Open animation ═══════ */
  :scope [slot="dialog"][data-open] [slot="panel"] {
    transition: transform var(--modal-duration) var(--modal-easing),
                opacity var(--modal-duration) var(--modal-easing);
    transform: scale(1);
    opacity: 1;
  }

  /* ═══════ Close animation ═══════ */
  :scope [slot="dialog"][data-closing] [slot="panel"] {
    transition: transform var(--modal-duration) var(--modal-easing),
                opacity var(--modal-duration) var(--modal-easing);
    transform: scale(0.95);
    opacity: 0;
  }

  /* ═══════ Header ═══════ */
  :scope [slot="header"] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--modal-pad-header) var(--modal-pad-body);
    border-bottom: 1px solid var(--modal-border);
    font-size: var(--modal-heading-size);
    font-weight: var(--modal-heading-weight);
    color: var(--modal-header-fg);
    flex-shrink: 0;
  }
  /* `[text]` gate — same drift class as button-ui / tag-ui / badge-ui /
     segment-ui (Apr-May 2026 phantom-gap arc). Without the `[text]`
     attribute selector, an empty `attr(text)` still generates a
     pseudo-element with `flex: 1` — it claims the row's free space and
     pushes any slotted title text-ui / icon-ui to the trailing edge,
     leaving only the close button on the right looking like the title.
     Gated on `[text]:not([text=""])` because modal/modal.class.js sets
     `header.setAttribute('text', this.text)` unconditionally; the
     defensive selector + class skip (see modal/modal.class.js render())
     close the same trap from both directions. */
  :scope [slot="header"][text]:not([text=""])::before {
    content: attr(text);
    flex: 1;
  }

  /* ═══════ Close button (button-ui) ═══════ */
  :scope [slot="close"] {
    flex-shrink: 0;
  }

  /* ═══════ Body ═══════ */
  :scope [slot="body"] {
    padding: var(--modal-pad-body);
    flex: 1;
    overflow: auto;
  }
  /* Form controls in the modal body fill the available width (a modal body is
     a form column, not a content-width row) — matches the field/input family's
     full-width behaviour in a real form. */
  :scope [slot="body"] :is(field-ui, input-ui, select-ui, textarea-ui, combobox-ui, tags-input-ui, color-input-ui, slider-ui) {
    width: 100%;
  }

  /* ═══════ Footer ═══════ */
  :scope [slot="footer"] {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--modal-footer-gap);
    padding: var(--modal-pad-footer) var(--modal-pad-body);
    border-top: 1px solid var(--modal-border);
    flex-shrink: 0;
  }
  /* No content → no footer chrome: an empty footer slot otherwise renders a
     dead band (border-top + padding) under the body. */
  :scope [slot="footer"]:empty { display: none; }
}
