/* Shared confirmation-modal component (extracted from donor_invoicing.css once
   the cashbook delete became its second consumer). A <dialog> opened by a
   confirm-style Stimulus controller (transition_confirm_controller and friends):
   .confirm-modal shell + .confirm-modal-inner body, a .confirm-lead paragraph,
   and a right-aligned .confirm-actions row. Feature files add variants on top
   (e.g. donor_invoicing.css's .donor-gate-modal, .donor-confirm-figures). */

/* ── M3 basic dialog: the one shell every <dialog> in the app shares ────────
   extra-large (28dp) corners, elevation 3, 280–560dp wide, over a 32% scrim;
   opens with the emphasized-decelerate easing. Feature files add only a width
   variant (.split-modal) and their content rules — never another copy of the
   shell.

   The container is remapped from M3's default surface-container-high to
   surface-container-lowest (white): our teal-seeded high tone is a grey that
   made every headline and paragraph read as text on grey, and a filled card
   inside it was grey on near-identical grey. M3 lets a component's surface
   role be remapped; on white, cards and fields inside the dialog get real
   contrast.

   The explicit inset/margin re-asserts the UA's top-layer centering, which the
   app's global `margin: 0` reset would otherwise break. */
:is(.confirm-modal, .travel-modal, .supporting-docs-modal, .split-modal, .expert-modal, .cp-modal) {
  position: fixed;
  inset: 0;
  margin: auto;
  border: none;
  border-radius: var(--md-sys-shape-corner-extra-large);
  padding: 0;
  width: min(35rem, calc(100vw - 2rem));
  min-width: min(17.5rem, calc(100vw - 2rem));
  height: fit-content;
  max-height: 90vh;
  overflow: auto;
  overscroll-behavior: contain;
  background: var(--md-sys-color-surface-container-lowest);
  color: var(--md-sys-color-on-surface-variant);
  box-shadow: var(--md-sys-elevation-level3);
  /* The dialog node may live inside a right-aligned actions cell and inherit
     its text-align — re-assert normal reading direction. */
  text-align: left;
  white-space: normal;
}

:is(.confirm-modal, .travel-modal, .supporting-docs-modal, .split-modal, .expert-modal, .cp-modal)[open] {
  animation: md-dialog-enter var(--md-sys-motion-duration-medium2) var(--md-sys-motion-easing-emphasized-decelerate);
}

@keyframes md-dialog-enter {
  from { opacity: 0; transform: translateY(-1rem) scale(0.98); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  :is(.confirm-modal, .travel-modal, .supporting-docs-modal, .split-modal, .expert-modal, .cp-modal)[open] { animation: none; }
}

:is(.confirm-modal, .travel-modal, .supporting-docs-modal, .split-modal, .expert-modal, .cp-modal)::backdrop {
  background: rgb(0 0 0 / 0.32);
}

/* 24dp padding on every side — on an inner wrapper, never the <dialog>: the
   sticky action row below measures its limit inside the dialog's own
   padding, so padding there would pull the actions up into the body. */
:is(.confirm-modal-inner, .travel-modal-form, .supporting-docs-modal-form, .split-modal-inner, .expert-modal-inner, .cp-modal > form) {
  padding: 1.5rem;
}

/* Headline: headline-small on-surface, 16dp above the body. An optional
   supporting line sits directly under it. It scrolls with the body — M3
   pins it, but Spencer preferred it unpinned. */
:is(.travel-modal-header, .supporting-docs-modal-header, .split-modal-header, .expert-modal-header, .cp-modal-header) {
  margin-bottom: 1rem;
}

/* Scoped by the dialog too, so a page rule like `.invoice-section h3` (the
   dialog may sit inside that section) can't out-rank the headline. */
:is(.confirm-modal, .travel-modal, .supporting-docs-modal, .split-modal, .expert-modal, .cp-modal)
  :is(.confirm-modal-inner, .travel-modal-header, .supporting-docs-modal-header, .split-modal-header, .expert-modal-header, .cp-modal-header) h3 {
  margin: 0;
  font: var(--md-sys-typescale-headline-small);
  letter-spacing: normal;
  color: var(--md-sys-color-on-surface);
}

:is(.confirm-modal, .travel-modal, .supporting-docs-modal, .split-modal, .expert-modal, .cp-modal) .confirm-modal-inner h3 { margin-bottom: 1rem; }

:is(.travel-modal-subtitle, .supporting-docs-modal-subtitle, .split-modal-subtitle, .expert-modal-subtitle, .cp-modal-subtitle) {
  margin: 0.25rem 0 0;
  font: var(--md-sys-typescale-body-medium);
  letter-spacing: var(--md-sys-typescale-body-medium-tracking);
  color: var(--md-sys-color-on-surface-variant);
}

.confirm-lead {
  margin: 0 0 0.75rem;
  font: var(--md-sys-typescale-body-medium);
  letter-spacing: var(--md-sys-typescale-body-medium-tracking);
  color: var(--md-sys-color-on-surface-variant);
}

/* Actions: trailing edge, 8dp apart, 24dp below the body; the dismissive text
   button sits left of the confirming one. Sticky, so on a dialog tall enough
   to scroll the buttons stay pinned at the bottom (M3: only the body scrolls);
   the negative margins carry the fill out to the dialog's edges.

   While body content sits hidden under the row, M3 separates the two with a
   divider. A scroll-driven animation on the dialog's own scroller shows it
   until the body is scrolled to its end; a dialog that doesn't scroll has an
   inactive timeline, so the divider never appears. */
:is(.confirm-actions, .travel-modal-actions, .supporting-docs-modal-actions, .split-modal-actions, .expert-modal-actions, .cp-modal-actions) {
  position: sticky;
  bottom: 0;
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-items: center;
  gap: 0.5rem;
  margin: 0 -1.5rem -1.5rem;
  padding: 1.5rem;
  border-top: 1px solid transparent;
  background: var(--md-sys-color-surface-container-lowest);
  animation: md-dialog-actions-divider linear both;
  animation-timeline: scroll(nearest block);
}

@keyframes md-dialog-actions-divider {
  from, 99% { border-top-color: var(--md-sys-color-outline-variant); }
  to        { border-top-color: transparent; }
}

/* The row's own top padding is the whole 24dp body-to-actions gap, so the
   element above it adds no margin of its own. */
:is(.confirm-modal, .travel-modal, .supporting-docs-modal, .split-modal, .expert-modal, .cp-modal)
  :has(+ :is(.confirm-actions, .travel-modal-actions, .supporting-docs-modal-actions, .split-modal-actions, .expert-modal-actions, .cp-modal-actions)) {
  margin-bottom: 0;
}

/* A leading action (e.g. "Use invoice period", "Back") parks on the start edge. */
:is(.confirm-actions, .travel-modal-actions, .supporting-docs-modal-actions, .split-modal-actions, .expert-modal-actions, .cp-modal-actions) .dialog-action-leading {
  margin-right: auto;
}

/* Dialog error line: error colour, body-small (the feature file places it). */
:is(.travel-modal-error, .expert-modal-error, .cp-modal-error) {
  font: var(--md-sys-typescale-body-small);
  letter-spacing: var(--md-sys-typescale-body-small-tracking);
  color: var(--md-sys-color-error);
}

/* A state-tinted confirm button keeps its colour but drops the action-bar
   uppercase, so it reads like the plain buttons beside it in the modal. */
.confirm-actions .btn-state {
  text-transform: none;
  letter-spacing: normal;
}

/* The trigger's button_to form and its <dialog> live in one inline-block
   wrapper, so the fixed-position dialog never disturbs the actions row. */
.transition-gate { display: inline-block; }
