/* ==========================================================================
   Modal
   ========================================================================== */

/* Extra iOS defense-in-depth alongside the .view-scroll lock in
   layout.css: stops the document itself from rubber-band bouncing while
   a modal is open, in case a gesture reaches past the backdrop. */
html.modal-open,
html.drawer-open {
  overscroll-behavior: none;
}

.modal-backdrop {
  position: fixed;
  /* Plain inset:0 - no explicit height. The dialog is centered (not
     edge/bottom anchored - see the mobile override below), so the
     backdrop only needs to dim + block touch across the screen; it
     doesn't need to be pixel-precise against the real visible viewport
     the way an edge-anchored sheet would. That precision requirement is
     exactly what earlier attempts (100dvh, then a JS-measured
     window.visualViewport custom property) were fighting to satisfy -
     removed in favor of just not depending on it. */
  inset: 0;
  background: rgba(0, 0, 0, 0.4);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  z-index: var(--z-modal-backdrop);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-6);
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-standard);
  /* Stops a touch-drag started on the dimmed background itself from
     panning/scrolling anything underneath (iOS routes an unhandled drag
     on a fixed overlay to the nearest scrollable ancestor otherwise).
     .modal below resets this so scrolling the dialog's own content still
     works normally. */
  touch-action: none;
}

.modal-backdrop.is-open {
  opacity: 1;
}

.modal {
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-2xl);
  box-shadow: var(--shadow-xl);
  width: 100%;
  max-width: 520px;
  max-height: 88vh;
  display: flex;
  flex-direction: column;
  transform: scale(0.94) translateY(12px);
  opacity: 0;
  transition: transform var(--dur-slow) var(--ease-spring),
    opacity var(--dur-base) var(--ease-standard);
  z-index: var(--z-modal);
  touch-action: auto; /* re-enable normal touch scrolling within the dialog, undoing .modal-backdrop's touch-action:none */
}

.modal-backdrop.is-open .modal {
  transform: scale(1) translateY(0);
  opacity: 1;
}

.modal__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-6) var(--space-6) var(--space-4);
  border-bottom: 1px solid var(--color-border);
}

.modal__title {
  font-size: var(--fs-title3);
  font-weight: var(--fw-semibold);
}

.modal__body {
  padding: var(--space-6);
  min-width: 0;
  /* Both axes stated explicitly. Setting overflow-y alone does NOT leave
     overflow-x as `visible`: per the overflow spec, when one axis is not
     visible/clip the other computes to `auto`, which silently turned this
     panel into a horizontal scroller. The width fixes above are what stop
     content from overflowing in the first place; this declares the intent
     - vertical scrolling only - so no sub-pixel rounding can reintroduce
     a sideways drag on touch. */
  overflow-x: hidden;
  overflow-y: auto;
  /* Same reservation as .view-scroll (see css/layout.css): adding a partial
     exit row can push the dialog past its max height, and without a stable
     gutter every field inside it would shift sideways at that moment. */
  scrollbar-gutter: stable;
  /* Stops scrolling the dialog's own content from "chaining" into the
     background once it hits the top/bottom edge (iOS rubber-band scroll
     otherwise bleeds through to whatever's behind the modal). */
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}

.modal__footer {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-6) var(--space-6);
}

/* "Discard your changes?" - shown instead of closing when a dirty form is
   dismissed by Escape / the X / the backdrop (Modal.open isDirty). */
.modal__discard {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-3);
  margin: 0 var(--space-6) var(--space-5);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  background: var(--color-warning-soft);
  border: 1px solid rgba(231, 156, 42, 0.35);
  animation: rise-in var(--dur-base) var(--ease-spring);
}

.modal__discard-text {
  flex: 1 1 160px;
  font-size: var(--fs-footnote);
  font-weight: var(--fw-medium);
}

/* ---- Mobile: smaller, capped-height dialog ----
   Simplest stable fix: instead of trying to precisely anchor a full-bleed
   sheet to the real edge of the screen (which needs exact viewport
   math - 100dvh, then a JS-measured window.visualViewport var, both
   proved unreliable on real devices), the mobile dialog just stays the
   same *kind* of box as desktop - centered, all corners rounded, same
   scale+fade entrance - only smaller and margined so it comfortably
   fits with room to spare. Content taller than the cap scrolls inside
   .modal__body (overflow-y: auto, already set above); the dialog box
   itself never needs to know the exact pixel height of the viewport.
   Breakpoint matches the mobile shell's own (880px, see layout.css). */
@media (max-width: 880px) {
  .modal-backdrop {
    padding: var(--space-4);
  }

  .modal {
    max-width: 100%;
    max-height: 70vh;
    min-width: 0; /* without this, a flex item's implicit min-content width can win over max-width:100% and force the dialog wider than the viewport */
  }

  .modal__header {
    padding: var(--space-5) var(--space-5) var(--space-3);
  }

  .modal__body {
    padding: var(--space-4) var(--space-5);
  }

  .modal__footer {
    padding: var(--space-3) var(--space-5) calc(var(--space-5) + env(safe-area-inset-bottom));
  }
}

