/* Shared dialog styling for the htmx modal. Auto-attached by SDC. */

.bs-htmx-modal {
  border: 0;
  border-radius: 6px;
  padding: 0;
  max-width: 39rem;
  width: 90vw;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.2);
  /* Column layout + a viewport-bounded height so the body (.__inner)
     scrolls internally and the footer can pin to the bottom instead of
     the whole dialog growing past the screen. */
  flex-direction: column;
  max-height: calc(100dvh - 2 * var(--padding-m));
  /* Query container so the two-column scroll behaviour adapts to the
     dialog's own width (not the viewport) — see the `@container
     bs-htmx-modal` rule below. */
  container: bs-htmx-modal / inline-size;
}

/* Apply the flex display only while open. Setting `display: flex` on the
   base selector would override the UA's `dialog:not([open]) { display:
   none }`, leaving the dialog content visible after close() (the backdrop
   disappears but the panel stays). */
.bs-htmx-modal[open] {
  display: flex;
}

/* Wider variant for content that needs more horizontal room, e.g.
 * two-column pickers. Opt in from the swap content by setting
 * `data-bs-htmx-modal-class="bs-htmx-modal--wide"` on any element
 * inside `#bs-htmx-modal-content`. modal.js applies it on afterSwap.
 */
.bs-htmx-modal--wide {
  max-width: 60rem;
}

/* Auto-expand the modal whenever it hosts a two-column layout, so the
   columns have room. This lives here (not in two_column.css) on purpose:
   modal.css is emitted on every page via hook_page_bottom, while
   two_column.css ships with the swapped-in fragment and applies a frame
   late. Resolving the width from always-loaded CSS lets the dialog open
   at its final size instead of visibly jumping from the base width once
   the fragment's stylesheet loads. Other modals keep the default width.
   `:has()` is widely supported in evergreen browsers; older browsers
   fall back to the standard width and the columns stack until the
   container query breakpoint. */
.bs-htmx-modal:has(.two-column) {
  max-width: 1100px;
}

.bs-htmx-modal::backdrop {
  background: rgba(0, 0, 0, 0.4);
}

.bs-htmx-modal__inner {
  padding: var(--padding-sm);
  /* The scrolling body within the column dialog, so the footer below can
     stay pinned to the bottom of the viewport. */
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}

/* The base `form` rule caps width (max-width: 900px / 60vw). Inside the
 * modal the form must fill the dialog so the body and the full-bleed
 * footer span the whole width and the footer reaches the modal edges.
 */
.bs-htmx-modal__inner form {
  max-width: none;
  margin: 0;
}

/* Wide two-column modals scroll each column independently instead of
   scrolling the whole body. Flexbox carries a height constraint down only one
   level at a time, so EVERY wrapper between the height-bounded modal body and
   the scrolling columns has to be a min-height:0 flex column that grows to
   fill its parent. The chain, top to bottom, is:

     .bs-htmx-modal__inner › .bs-htmx-form › form › .two-column ›
       .two-column__grid › .two-column__column

   Shorten it only by removing a wrapper from the DOM — dropping any single
   link re-breaks per-column scrolling. */
.bs-htmx-modal:has(.two-column) {
  /* The body clips; the columns below own the scrolling (overriding the
     base .__inner `overflow-y: auto`). */
  & .bs-htmx-modal__inner {
    overflow: hidden;
  }

  /* Each flex wrapper in the chain: a column box that grows to fill its
     parent and lets its content shrink. (.__inner already gets
     `flex: 1 1 auto` + `min-height: 0` from its base rule above.) */
  & .bs-htmx-modal__inner,
  & .bs-htmx-form,
  & .bs-htmx-form > form,
  & .two-column {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
  }

  /* The grid grows (as a flex item of .two-column) and bounds its single row
     so the columns can't push it taller than the available height. */
  & .two-column__grid {
    flex: 1 1 auto;
    min-height: 0;
    grid-template-rows: minmax(0, 1fr);
  }

  /* Each column is the actual scroll viewport. */
  & .two-column__column {
    min-height: 0;
    overflow-y: auto;
    padding-bottom: var(--padding-m);
  }
}

/* Single-column (narrow) state, keyed on the DIALOG's own width via a
   container query (`.bs-htmx-modal` is the named container) rather than the
   viewport — so it tracks the dialog regardless of how wide the dialog got.
   The two_column SDC collapses its grid to one column once `.two-column`
   drops below 720px; that happens just under this 47.5rem dialog width
   (dialog = `.two-column` + the ~2.25vw `.__inner` padding each side). We
   unwind a hair before the collapse, so there's never a stacked-but-pinned
   window: the pinned chain clamps every wrapper to the dialog height and pins
   the grid row to `minmax(0, 1fr)`, which would squeeze a stacked column into
   a fraction of the height and (with the columns no longer clipping) spill it
   over the next column and the footer. Reverting to natural block flow lets
   the content stack at its true height and scroll as one body. */
@container bs-htmx-modal (max-width: 47.5rem) {
  .bs-htmx-modal:has(.two-column) {
    /* Body scrolls as one; children flow naturally instead of as a pinned
       flex chain. */
    & .bs-htmx-modal__inner {
      display: block;
      overflow-y: auto;
    }

    & .bs-htmx-form,
    & .bs-htmx-form > form,
    & .two-column {
      display: block;
    }

    /* Rows size to content (was minmax(0, 1fr) for the per-column split). */
    & .two-column__grid {
      grid-template-rows: auto;
    }

    & .two-column__column {
      overflow: visible;
    }
  }
}

/* Form actions container — right-aligned buttons pinned to the bottom of
 * the scrolling modal body so they stay visible while the content
 * scrolls. The negative margins full-bleed the bar to the modal edges
 * (cancelling the .__inner padding) and the opaque background masks
 * content scrolling beneath it.
 */
.bs-htmx-modal__actions,
.bs-htmx-modal .form-actions {
  display: flex;
  flex-shrink: 0;
  justify-content: flex-end;
  gap: var(--padding-s);
  position: sticky;
  bottom: calc(var(--padding-sm) * -1);
  margin: 0 calc(var(--padding-sm) * -1) calc(var(--padding-sm) * -1);
  padding: var(--padding-s) var(--padding-sm);
  background: var(--color-white);
  border-top: 1px solid var(--color-border);
  max-width: none;
}
