/**
 * Modal — dialog component on the native <dialog> element.
 * Replaces heritage wv_Dialog / wv_SystemDialog / wv_QuickDialog / jQuery UI .dialog().
 * Spec: docs/specs/2026-06-10-modal-design.md
 *
 * Zero new :root tokens. Element-scoped width hooks only (--modal-width-*).
 *
 * Sections:
 *   1. Card chrome (Figma Module 4644:9732 pinned values)
 *   2. Sizes
 *   3. Slots (header / body / footer)
 *   4. Close button
 *   5. Scrim (::backdrop)
 *   6. Elevation tiers
 *   7. Entrance animation + reduced motion
 *   8. Inline docs mode
 *   9. Destructive family            (Phase 2)
 *  10. Window features + dock bar    (Phase 3)
 */

/* ─── 1. Card chrome ─── */

.modal {
  /* element-scoped width hooks — consumer-overridable (--table-checkbox-cell-width precedent) */
  --modal-width-sm: 420px;
  --modal-width-md: 560px;
  --modal-width-lg: 720px;

  width: min(var(--modal-width-sm), calc(100vw - 32px));
  max-height: 85vh;

  /* re-assert UA centering — base.css's universal margin reset kills the
     UA stylesheet's dialog { margin: auto } that centers top-layer dialogs */
  margin: auto;

  padding: var(--spacing-8) var(--spacing-6);   /* 32px vertical / 24px horizontal (Figma) */
  background: var(--bg-primary);
  border: 1px solid var(--border-secondary);
  border-radius: var(--radius-md);              /* 8px */
  box-shadow: var(--shadow-2xl);                /* Elevation 2 — base modal */
  color: var(--text-primary);
  font-family: var(--font-primary);
}

/* Gate flex on [open] — the UA hides closed dialogs with display:none, and any
   author display value would override that (cascade origin), showing closed dialogs. */
.modal[open] {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-4);                        /* 16px between header / body / footer */
}

/* ─── 2. Sizes ─── */

.modal[data-size="md"] { width: min(var(--modal-width-md), calc(100vw - 32px)); }
.modal[data-size="lg"] { width: min(var(--modal-width-lg), calc(100vw - 32px)); }

/* ─── 3. Slots ─── */

.modal-header {
  flex: 0 0 auto;
  /* keep long titles clear of the injected ✕ (24px button at 11px inset) */
  padding-right: var(--spacing-6);
}

.modal-title {
  margin: 0;
  font-size: var(--font-size-md);               /* 16px */
  line-height: var(--line-height-md);           /* 24px */
  font-weight: var(--font-weight-medium);       /* 500 */
  color: var(--text-primary);
}

.modal-subtitle {
  margin: 2px 0 0;                              /* 2px below the title (Figma) */
  font-size: var(--font-size-sm);               /* 14px */
  line-height: var(--line-height-sm);           /* 20px */
  font-weight: var(--font-weight-regular);
  color: var(--text-secondary);
}

.modal-body {
  flex: 1 1 auto;
  min-height: 0;                                /* flex items refuse to shrink below content height — required for internal scroll */
  overflow: auto;                               /* long forms scroll internally; header/footer stay pinned */
  padding-top: var(--spacing-1);                /* 4px (Figma divider geometry) */
}

/* The divider lives on the body container, not the footer (Figma) — and only
   when a footer actually follows. */
.modal-body:has(+ .modal-footer) {
  border-bottom: 1px solid var(--border-secondary);
  padding-bottom: var(--spacing-4);             /* 16px above the divider */
}

.modal-footer {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--spacing-2);
}

.modal-footer-left {
  display: flex;
  align-items: center;
  gap: var(--spacing-2);
}

.modal-footer-actions {
  display: flex;
  align-items: center;
  gap: var(--spacing-2);                        /* 8px between buttons (Figma) */
  margin-left: auto;                            /* right-aligned even without a -left slot */
}

/* ─── 4. Close button ─── */

/* Direct child of the dialog. The modal dialog is position:fixed (UA), so it is
   the containing block — 11px insets land relative to the card edge (Figma). */
.modal-close {
  position: absolute;
  top: 11px;
  right: 11px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  padding: var(--spacing-1);                    /* 4px */
  border: 0;
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--fg-quinary);
  font-size: 16px;                              /* fa-xmark-large glyph */
  line-height: 1;
  cursor: pointer;
}

.modal-close:hover {
  color: var(--fg-quinary-hover);
  background: var(--bg-secondary-hover);
}

.modal-close:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

/* ─── 5. Scrim ─── */

.modal::backdrop {
  background: var(--bg-overlay);                /* first consumer of this token */
}

/* Heritage-style faint dimming for read-the-chart-behind migration scenarios (§7) */
.modal[data-scrim="light"]::backdrop {
  background: rgba(136, 136, 136, 0.2);
}

/* ─── 6. Elevation tiers ─── */

/* Engine stamps data-elevation="3" on a dialog opened while another is open (§8).
   The base modal keeps --shadow-2xl and dims further under the stacked dialog's
   own ::backdrop for free. */
.modal[data-elevation="3"] {
  box-shadow: var(--shadow-3xl);
}

/* ─── 7. Entrance animation ─── */

/* Entrance-only: fade + slight scale from @starting-style on first render.
   Dismiss is an intentional snap-off (Tooltip precedent) — no exit transition. */
.modal {
  transition: opacity 0.15s ease, transform 0.15s ease;
}

@starting-style {
  .modal[open] {
    opacity: 0;
    transform: scale(0.97);
  }
}

.modal::backdrop {
  transition: opacity 0.15s ease;
}

@starting-style {
  .modal[open]::backdrop {
    opacity: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .modal {
    transition: opacity 0.15s ease;             /* opacity-only — no transform */
  }
  @starting-style {
    .modal[open] {
      transform: none;
    }
  }
}

/* ─── 8. Inline docs mode ─── */

/* Variant galleries: <dialog class="modal modal-inline" open> renders in-flow —
   no top layer, no scrim, no trap (plain [open] never enters the top layer).
   position:relative keeps it in flow AND keeps the ✕ anchored to the card. */
.modal-inline[open] {
  position: relative;
  margin: 0;
}

/* ─── 9. Destructive family ─── */

/* Tinted card — the loud variant. The white-card destructive confirm is just a
   regular .modal whose primary action is .btn-primary-error. */
.modal-destructive {
  background: var(--bg-error-primary);            /* error-25 light / error-950 dark */
  border-color: var(--border-error-subtle);       /* error-300 light / error-600 dark */
}

/* The body↔footer divider inherits the card border color on tinted cards */
.modal-destructive .modal-body:has(+ .modal-footer) {
  border-bottom-color: var(--border-error-subtle);
}

/* Warning line — authored text (e.g. "ÞESSI AÐGERÐ ER ÓAFTURKRÆF"), never injected */
.modal-warning {
  margin: 0;
  font-size: var(--font-size-xs);                 /* 12px */
  line-height: var(--line-height-sm);
  font-weight: var(--font-weight-semibold);       /* 600 */
  color: var(--text-error-primary);               /* error-700 light / error-400 dark */
}

/* modalConfirm() message paragraph */
.modal-confirm-message {
  margin: 0;
  font-size: var(--font-size-sm);
  line-height: var(--line-height-sm);
  color: var(--text-secondary);
}

/* Stack confirm-body children (message / warning / type-to-confirm) with breathing room */
.modal-body > .modal-confirm-message + .modal-warning,
.modal-body > .modal-confirm-message + .modal-typeconfirm,
.modal-body > .modal-warning + .modal-typeconfirm {
  margin-top: var(--spacing-3);
}

/* Type-to-confirm block — reuses .input-label / .input-field / .input-error wholesale */
.modal-typeconfirm {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-1);
}

.modal-typeconfirm-error {
  margin: 0;
  font-size: var(--font-size-sm);
  line-height: var(--line-height-sm);
  color: var(--text-error-primary);
}

/* ─── 10. Window features (opt-in, heritage parity) ─── */

/* [– ▢ ✕] cluster — replaces the lone ✕ position for opted-in dialogs */
.modal-controls {
  position: absolute;
  top: 11px;
  right: 11px;
  display: flex;
  align-items: center;
  gap: var(--spacing-1);
}

/* inside the cluster the ✕ flows with its siblings */
.modal-controls .modal-close {
  position: static;
}

.modal-control {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  padding: var(--spacing-1);
  border: 0;
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--fg-quinary);                     /* uniform — heritage hover-red/green retired (§16) */
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
}

.modal-control:hover {
  color: var(--fg-quinary-hover);
  background: var(--bg-secondary-hover);
}

.modal-control:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

/* Draggable: header is the handle */
.modal[data-draggable] .modal-header {
  cursor: move;
  user-select: none;
}

/* …but drag is inert while maximized (engine guard) — don't promise it */
.modal[data-maximized] .modal-header {
  cursor: default;
}

/* The entrance animation transitions transform — that would lag pointer-drag by
   150ms. Draggable dialogs keep the fade only. */
.modal[data-draggable] {
  transition: opacity 0.15s ease;
}

/* Maximized: near-fullscreen, body flexes into the space */
.modal[data-maximized] {
  width: calc(100vw - 48px);
  height: calc(100vh - 48px);
  max-height: none;
}

/* Minimized dock — bars stack upward from the bottom-right corner */
.modal-minimized-dock {
  position: fixed;
  right: var(--spacing-4);
  bottom: var(--spacing-4);
  z-index: var(--z-dialog);            /* the one place the modal still needs z-index */
  display: flex;
  flex-direction: column-reverse;      /* newest bar lowest, stacking upward */
  gap: var(--spacing-2);
}

.modal-minimized-bar {
  display: flex;
  align-items: center;
  gap: var(--spacing-2);
  max-width: 320px;
  padding: var(--spacing-2) var(--spacing-3);
  background: var(--bg-primary);
  border: 1px solid var(--border-secondary);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-2xl);
}

.modal-minimized-title {
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--font-size-sm);
  line-height: var(--line-height-sm);
  font-weight: var(--font-weight-medium);
  color: var(--text-primary);
}

/* iframe body content — ordinary body content that fills the free area */
.modal-has-iframe {
  height: 85vh;                        /* iframe modals need real height to be useful */
}

.modal-has-iframe .modal-body {
  display: flex;
}

.modal-iframe {
  flex: 1 1 auto;
  width: 100%;
  border: 0;
}
