/* Dialog shell component — the converged modal-<dialog> surface shared by the
   card dialogs (photo viewer, install-nudge, workbench palette + cheatsheet,
   ingredient review). Owns chrome only: card background, hairline border,
   radius, dialog shadow, tokened backdrop, the bloop entrance, and the
   transition-owned exit (#4268 — entrance stays keyframe-owned because a
   running animation overrides the transition on the same properties, so the
   transition only ever fires on close). Consumers
   style sizing/layout/content on their OWN class and tune inner padding via
   --dialog-padding; never re-declare properties or re-style .dialog* from a
   page sheet (rake lint:hig). The search overlay is not a consumer — it's a
   full-viewport transparent container, an explicit #3099 non-goal.

   Public API (variables only; set on the instance's own class):
     --dialog-surface        (--content-card-bg)
     --dialog-border-color   (--rule)
     --dialog-radius         (--radius-lg)
     --dialog-padding        (--space-4)

   Convergence (#3170): the five dialogs split three ways on every axis —
   surfaces --ground / --content-card-bg / none, borders --text / --rule, radii
   --radius-md / 12px / 0.25rem, and only two of them animated at all. We
   converged on the card tokens the newest, most-polished dialogs (the search
   panel and install-nudge) already used — the elevated --content-card-bg
   surface, the --rule hairline, and the friendlier --radius-lg card corner —
   and handed all five the bloop entrance the vocabulary defines. The global
   prefers-reduced-motion gate in base.css already neutralizes the animation.

   Collaborators: components/_dialog.html.erb, consumer controllers (open/close).
   State ladder: docs/wiki/style.md § The state ladder. */

.dialog {
  border: 1px solid var(--dialog-border-color, var(--rule));
  border-radius: var(--dialog-radius, var(--radius-lg));
  background: var(--dialog-surface, var(--content-card-bg));
  color: var(--text);
  box-shadow: var(--shadow-dialog);
  padding: var(--dialog-padding, var(--space-4));
  animation: bloop var(--duration-bloop) var(--ease-bloop);
  /* allow-discrete holds the dialog in the top layer while the exit fade
     lands; exits run faster than entrances (--duration-fast vs -bloop). */
  transition:
    opacity var(--duration-fast) ease,
    transform var(--duration-fast) ease,
    overlay var(--duration-fast) ease allow-discrete,
    display var(--duration-fast) ease allow-discrete;
}

/* Exit target — reached on Escape, backdrop click, cancel, or .close(). */
.dialog:not([open]) {
  opacity: 0;
  transform: scale(0.96);
}

.dialog::backdrop {
  background: var(--dialog-backdrop);
  animation: fade-in var(--duration-normal) ease-out;
  transition:
    opacity var(--duration-fast) ease,
    overlay var(--duration-fast) ease allow-discrete,
    display var(--duration-fast) ease allow-discrete;
}

.dialog:not([open])::backdrop {
  opacity: 0;
}

/* Close-button placement (#3480): the HIG rule is "top-right corner, always"
   (docs/wiki/style.md § The component layer). Consumers with no bespoke
   header of their own (photo viewer, transfer dialog) apply .dialog-close
   directly; dialogs with their own header row achieve the same corner via
   flex order instead — this rule is additive, not the only mechanism. A
   dialog shown via showModal() already gets position: fixed from the UA
   stylesheet (dialog:modal), so .dialog itself needs no position override
   for .dialog-close to anchor correctly — do not add position: relative to
   .dialog, it would fight the UA rule that centers the modal. */
.dialog-close {
  position: absolute;
  top: var(--space-3);
  right: var(--space-3);
}
