/* Mobile dialogs are full-screen workspaces, never floating desktop cards. */
@media (max-width: 980px) {
  html,
  body {
    width: 100%;
    max-width: 100%;
    overflow-x: clip;
    touch-action: pan-x pan-y;
  }

  body.mobile-modal-open,
  body.services-games-open {
    overflow: hidden;
    overscroll-behavior: none;
  }

  /* In an installed iOS web app the status-bar canvas can sit outside the CSS
     viewport. Paint that root canvas with the same surface as Games so it
     cannot show up as a contrasting strip above or below the full-screen
     dialog. */
  html:has(> body.services-games-open),
  body.services-games-open {
    background-color: var(--panel, #fff);
  }

  /* Full-screen tools own the phone viewport. Keep the fixed navigation's
     compositor/layout layer alive underneath dialogs, but make it unavailable.
     iOS WebKit can fail to repaint a bar that changed display:none -> grid
     when a full-screen dialog closes (most visibly after Course Rubric). */
  body.mobile-modal-open .feature-nav,
  body.services-games-open .feature-nav {
    visibility: hidden !important;
    opacity: 0 !important;
    pointer-events: none !important;
  }

  /* The keyboard transition still removes the bar from layout entirely: its
     shrinking visual viewport otherwise leaves a tappable invisible strip. */
  body.mobile-keyboard-open .feature-nav {
    display: none !important;
  }

  /* Setup already has a fixed header/footer and one dedicated scrolling body.
     Do not let the generic full-screen-dialog rule turn its outer overlay into
     a second scroll surface: nested momentum scrolling made short upward
     swipes appear to do almost nothing on iPhone. */
  body .setup-overlay.setup-overlay[role="dialog"][aria-modal="true"] {
    display: grid !important;
    overflow: hidden !important;
    overscroll-behavior: none !important;
    touch-action: none !important;
  }

  .setup-overlay[role="dialog"][aria-modal="true"] > .setup-card {
    min-height: 0 !important;
    max-height: 100% !important;
  }

  .setup-overlay[role="dialog"][aria-modal="true"] .setup-body {
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    scroll-padding-block: 10px;
    touch-action: pan-y;
    -webkit-overflow-scrolling: touch;
  }

  /* Safari can drop the complex top-level-dialog selector below. app.js marks
     the outer dialog and its host so phones also have this simple fallback. */
  .mobile-viewport-modal-host {
    position: fixed !important;
    inset: auto !important;
    top: var(--app-live-viewport-top, 0px) !important;
    right: auto !important;
    bottom: auto !important;
    left: var(--app-live-viewport-left, 0px) !important;
    box-sizing: border-box !important;
    width: var(--app-live-viewport-width, 100dvw) !important;
    min-width: 0 !important;
    max-width: none !important;
    height: var(--app-live-viewport-height, 100dvh) !important;
    min-height: var(--app-live-viewport-height, 100dvh) !important;
    max-height: var(--app-live-viewport-height, 100dvh) !important;
    margin: 0 !important;
    padding: 0 !important;
    overflow: hidden !important;
    place-items: stretch !important;
    align-items: stretch !important;
    border-radius: 0 !important;
    overscroll-behavior: none;
    touch-action: pan-y;
  }

  [role="dialog"][aria-modal="true"].mobile-viewport-dialog:not([data-mobile-dialog-float]):not(.setup-overlay) {
    position: fixed !important;
    inset: auto !important;
    top: var(--app-live-viewport-top, 0px) !important;
    right: auto !important;
    bottom: auto !important;
    left: var(--app-live-viewport-left, 0px) !important;
    z-index: 10001 !important;
    box-sizing: border-box !important;
    width: var(--app-live-viewport-width, 100dvw) !important;
    min-width: 0 !important;
    max-width: none !important;
    height: var(--app-live-viewport-height, 100dvh) !important;
    min-height: var(--app-live-viewport-height, 100dvh) !important;
    max-height: var(--app-live-viewport-height, 100dvh) !important;
    margin: 0 !important;
    border-top: 0 !important;
    border-right: 0 !important;
    border-bottom: 0 !important;
    border-left: 0 !important;
    border-radius: 0 !important;
    overflow-x: hidden !important;
    overflow-y: auto !important;
    scroll-padding-bottom: var(--a1-safe-bottom);
    overscroll-behavior: contain;
    touch-action: pan-y;
    -webkit-overflow-scrolling: touch;
  }

  /* Floating cards/sheets (data-mobile-dialog-float) never span under the
     status bar or home indicator — their backdrop reserves the safe areas —
     so their headers/footers must NOT absorb the insets. Adding the status-bar
     inset to a bottom sheet's heading painted a tall blank band above it. */
  [role="dialog"][aria-modal="true"].mobile-viewport-dialog:not([data-mobile-dialog-float]) > :where(
    header,
    [class*="modal-header"],
    [class*="dialog-header"],
    [class$="-header"],
    [class*="-header "],
    [class$="-head"],
    [class*="-head "],
    [class*="modal-heading"],
    [class$="-heading"],
    [class*="-heading "]
  ) {
    position: sticky !important;
    top: 0 !important;
    z-index: 10;
    padding-top: calc(14px + var(--a1-safe-top)) !important;
    padding-right: max(14px, var(--a1-safe-right)) !important;
    padding-left: max(14px, var(--a1-safe-left)) !important;
    background-color: var(--panel) !important;
  }

  [role="dialog"][aria-modal="true"].mobile-viewport-dialog:not([data-mobile-dialog-float]) > :where(
    footer,
    [class*="modal-footer"],
    [class*="dialog-footer"],
    [class$="-footer"],
    [class*="-footer "]
  ) {
    padding-bottom: calc(14px + var(--a1-safe-bottom)) !important;
  }

  /* Game dialogs reserve the safe-area insets on their own outer shell. */
  [role="dialog"][aria-modal="true"].mobile-viewport-dialog.mini-game-dialog > .mini-game-header,
  [role="dialog"][aria-modal="true"].mobile-viewport-dialog.quick-memory-dialog > .quick-memory-modal-header,
  [role="dialog"][aria-modal="true"].mobile-viewport-dialog.number-drop-dialog > .number-drop-header,
  [role="dialog"][aria-modal="true"].mobile-viewport-dialog.missing-number-dialog > .missing-number-header,
  [role="dialog"][aria-modal="true"].mobile-viewport-dialog.estimation-dialog > .estimation-header,
  [role="dialog"][aria-modal="true"].mobile-viewport-dialog.color-hunt-dialog > .color-hunt-header,
  [role="dialog"][aria-modal="true"].mobile-viewport-dialog.math-garden-dialog > .math-garden-header {
    padding-top: 14px !important;
  }

  /* Backdrops must cover the LAYOUT viewport, not the live visual viewport:
     sizing them with --app-live-viewport-height made every scrim shrink to
     the keyboard-free strip the moment the keyboard opened, exposing the page
     behind the dialog. inset:0 covers the layout viewport keyboard-free; the
     negative bottom adds the keyboard height as slack because iOS can leave
     fixed layers at a stale position while it pans to the focused field. The
     dialog card inside still tracks the live viewport so it stays visible. */
  :where(
    [class$="-backdrop"],
    [class*="-backdrop "],
    [class$="-overlay"],
    [class*="-overlay "]
  ):has(> [role="dialog"][aria-modal="true"]) {
    position: fixed !important;
    inset: 0 !important;
    bottom: calc(-1 * var(--app-keyboard-inset, 0px)) !important;
    z-index: 10000 !important;
    box-sizing: border-box !important;
    width: auto !important;
    min-width: 0 !important;
    max-width: none !important;
    height: auto !important;
    min-height: 0 !important;
    max-height: none !important;
    margin: 0 !important;
    padding: 0 !important;
    overflow: hidden !important;
    place-items: stretch !important;
    align-items: stretch !important;
    border-radius: 0 !important;
    overscroll-behavior: none;
    touch-action: pan-y;
  }

  /* data-mobile-dialog-float: the dialog stays a centered card with margins
     instead of owning the whole viewport (calendar compose). The backdrop
     still covers the screen; only the card inside it floats. */
  :where(
    [class$="-backdrop"],
    [class*="-backdrop "],
    [class$="-overlay"],
    [class*="-overlay "]
  ):has(> [role="dialog"][aria-modal="true"][data-mobile-dialog-float]) {
    /* No display here: the backdrop's own hidden state must keep display:none. */
    place-items: center !important;
    align-items: center !important;
    /* The safe areas are reserved here, on the backdrop, so a tall centered
       card cannot slide under the Dynamic Island or the home indicator. The
       card's own header/footer therefore never add the insets themselves. */
    padding:
      max(14px, var(--a1-safe-top))
      max(14px, var(--a1-safe-right))
      max(14px, var(--a1-safe-bottom))
      max(14px, var(--a1-safe-left)) !important;
    overflow: auto !important;
  }

  /* The legacy phone sheet rules in styles.css still force 100dvh on the
     home add/edit modal; floated instances go back to being a card. */
  .home-add-modal[data-mobile-dialog-float] {
    width: min(520px, calc(var(--app-live-viewport-width, 100dvw) - 28px));
    height: auto;
    max-height: calc(var(--app-live-viewport-height, 100dvh) - 28px);
    border: 1px solid var(--line-soft);
    border-radius: 16px;
  }

  .home-add-modal[data-mobile-dialog-float] .home-add-modal-header {
    padding-top: 14px;
  }

  .home-add-modal[data-mobile-dialog-float] .home-add-modal-body {
    padding-bottom: 16px;
  }

  [role="dialog"][aria-modal="true"][data-mobile-dialog-float] {
    width: min(560px, calc(var(--app-live-viewport-width, 100dvw) - 28px));
    max-width: calc(var(--app-live-viewport-width, 100dvw) - 28px);
    /* Match the backdrop's actual safe-area padding. Subtracting only 28px
       let tall cards extend behind the status bar on notched phones. */
    box-sizing: border-box;
    max-height: calc(var(--app-live-viewport-height, 100dvh) - max(14px, var(--a1-safe-top, 0px)) - max(14px, var(--a1-safe-bottom, 0px)));
    border-radius: 16px;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
  }

  [role="dialog"][aria-modal="true"].pe-warning-card[data-mobile-dialog-float] {
    width: min(340px, calc(var(--app-live-viewport-width, 100dvw) - 48px));
    max-width: calc(var(--app-live-viewport-width, 100dvw) - 48px);
    max-height: calc(var(--app-live-viewport-height, 100dvh) - 48px);
  }

  [role="dialog"][aria-modal="true"].pe-time-card[data-mobile-dialog-float] {
    width: min(320px, calc(var(--app-live-viewport-width, 100dvw) - 48px));
    max-width: calc(var(--app-live-viewport-width, 100dvw) - 48px);
    max-height: calc(var(--app-live-viewport-height, 100dvh) - 48px);
  }

  /* A rules/result dialog can live inside an already-open game dialog. Only
     the outer dialog owns the viewport; nested dialogs keep their component
     sizing so they do not create two competing full-screen scroll surfaces. */
  [role="dialog"][aria-modal="true"]:not(
    [role="dialog"][aria-modal="true"] [role="dialog"][aria-modal="true"]
  ):not([data-mobile-dialog-float]):not(.setup-overlay) {
    position: fixed !important;
    inset: auto !important;
    top: var(--app-live-viewport-top, 0px) !important;
    right: auto !important;
    bottom: auto !important;
    left: var(--app-live-viewport-left, 0px) !important;
    z-index: 10001 !important;
    box-sizing: border-box !important;
    width: var(--app-live-viewport-width, 100dvw) !important;
    min-width: 0 !important;
    max-width: none !important;
    height: var(--app-live-viewport-height, 100dvh) !important;
    min-height: var(--app-live-viewport-height, 100dvh) !important;
    max-height: var(--app-live-viewport-height, 100dvh) !important;
    margin: 0 !important;
    border-top: 0 !important;
    border-right: 0 !important;
    border-bottom: 0 !important;
    border-left: 0 !important;
    border-radius: 0 !important;
    overflow-x: hidden !important;
    overflow-y: auto !important;
    scroll-padding-top: var(--a1-safe-top);
    scroll-padding-bottom: var(--a1-safe-bottom);
    overscroll-behavior: contain;
    touch-action: pan-y;
    -webkit-overflow-scrolling: touch;
  }

  [role="dialog"][aria-modal="true"]:not(
    [role="dialog"][aria-modal="true"] [role="dialog"][aria-modal="true"]
  ) > :where(
    header,
    footer,
    form,
    section,
    article,
    [class*="header"],
    [class*="body"],
    [class*="footer"],
    [class*="actions"]
  ) {
    box-sizing: border-box;
    min-width: 0;
    max-width: 100%;
  }

  [role="dialog"][aria-modal="true"]:not(
    [role="dialog"][aria-modal="true"] [role="dialog"][aria-modal="true"]
  ):not([data-mobile-dialog-float]) > :where(
    header,
    [class*="modal-header"],
    [class*="dialog-header"],
    [class$="-header"],
    [class*="-header "],
    [class$="-head"],
    [class*="-head "],
    [class*="modal-heading"],
    [class$="-heading"],
    [class*="-heading "]
  ) {
    position: sticky !important;
    top: 0 !important;
    z-index: 10;
    /* The safe area and the component's normal breathing room are additive.
       Using max() put controls directly on the safe-area boundary and allowed
       the system clock/battery row to overlap them on some iPhones.
       Float dialogs are excluded: their backdrop reserves the safe areas, and
       this inset inside a bottom sheet's heading was the blank band above
       "Add event". */
    padding-top: calc(14px + var(--a1-safe-top)) !important;
    background-color: var(--panel) !important;
  }

  /* Registration names its in-flow header "nav", so it is intentionally not
     caught by the broad header selectors above. Reserve the iPhone status-bar
     inset here; the generic backdrop rule resets outer padding to zero. */
  .roadmap-course-detail-modal > .roadmap-course-detail-nav {
    min-height: calc(58px + var(--a1-safe-top));
    padding-top: var(--a1-safe-top) !important;
    padding-right: var(--a1-safe-right);
    padding-left: var(--a1-safe-left);
    background-color: var(--panel) !important;
  }

  [role="dialog"][aria-modal="true"]:not(
    [role="dialog"][aria-modal="true"] [role="dialog"][aria-modal="true"]
  ):not([data-mobile-dialog-float]) > :where(
    footer,
    [class*="modal-footer"],
    [class*="dialog-footer"],
    [class$="-footer"],
    [class*="-footer "]
  ) {
    padding-bottom: calc(14px + var(--a1-safe-bottom)) !important;
  }

  [role="dialog"][aria-modal="true"] :where(input, select, textarea) {
    box-sizing: border-box;
    max-width: 100%;
    font-size: 16px !important;
  }

  [role="dialog"][aria-modal="true"] :where(img, video, canvas, svg, iframe, table) {
    max-width: 100%;
  }

  .home-add-modal {
    display: grid !important;
    grid-template-rows: auto minmax(0, 1fr) !important;
    padding: 0 !important;
    overflow: hidden !important;
  }

  .home-add-modal-body {
    min-height: 0;
    overflow-x: hidden !important;
    overflow-y: auto !important;
    padding-bottom: max(16px, var(--a1-safe-bottom)) !important;
    overscroll-behavior: contain;
  }

  /* Games is a bounded two-row workspace: the header stays available and the
     list is the sole scroll owner. The old hidden overflow clipped the final
     row and left no ancestor with scrollable overflow. */
  .services-modal[data-services-games-modal] > [role="dialog"][aria-modal="true"].services-modal-dialog.mobile-viewport-dialog,
  .services-modal[data-game-leaderboard-modal] > [role="dialog"][aria-modal="true"].services-modal-dialog.mobile-viewport-dialog {
    position: fixed !important;
    inset: auto !important;
    top: var(--app-live-viewport-top, 0px) !important;
    right: auto !important;
    bottom: auto !important;
    left: var(--app-live-viewport-left, 0px) !important;
    display: grid !important;
    grid-template-rows: auto minmax(0, 1fr) !important;
    gap: 0 !important;
    width: var(--app-live-viewport-width, 100dvw) !important;
    height: var(--app-live-viewport-height, 100dvh) !important;
    max-width: none !important;
    max-height: none !important;
    margin: 0 !important;
    padding: 0 !important;
    border-radius: 0 !important;
    overflow-x: hidden !important;
    overflow-y: hidden !important;
  }

  .services-modal[data-services-games-modal],
  .services-modal[data-game-leaderboard-modal] {
    padding: 0 !important;
  }

  /* Inset card, not full bleed: the list keeps its own border and radius and
     floats 14px off the glass edges. The grid stays the sole scroll owner. */
  .services-modal[data-services-games-modal] .services-games-grid,
  .services-modal[data-game-leaderboard-modal] .quick-memory-leaderboard-list {
    min-height: 0 !important;
    overflow-x: hidden !important;
    overflow-y: auto !important;
    margin: 0 14px max(14px, var(--a1-safe-bottom));
    border-radius: 12px;
    padding-bottom: 8px;
    scroll-padding-bottom: 8px;
    overscroll-behavior: contain;
    touch-action: pan-y;
    -webkit-overflow-scrolling: touch;
  }

  .services-modal[data-services-games-modal] .services-modal-header,
  .services-modal[data-game-leaderboard-modal] .services-modal-header {
    padding-bottom: 14px !important;
  }

  /* The mode picker is three buttons, not a workspace: full-screen pinning
     left it 83% blank with the buttons pinned to the top and the X grazing
     the Friends card. Center the content column instead. */
  .game-mode-modal > [role="dialog"][aria-modal="true"].game-mode-card {
    display: grid;
    align-content: center;
    padding: 24px;
  }

  /* Keep this after the generic dialog workspace rules above. Longhand
     overflow declarations there intentionally make most dialogs scroll, but
     setup's inner .setup-body is its sole scroll owner. */
  body .setup-overlay.setup-overlay[role="dialog"][aria-modal="true"] {
    overflow-x: hidden !important;
    overflow-y: hidden !important;
  }
}

.email-dashboard-actions {
  display: flex !important;
  align-items: center;
  justify-content: flex-end;
  gap: 8px !important;
}

.email-dashboard-actions .email-close-button {
  flex: 0 0 auto;
}

@media (max-width: 360px) {
  .scenic-recall-dialog .scenic-recall-palette,
  .scenic-recall-dialog.is-sr-duel .scenic-recall-palette {
    flex-wrap: nowrap;
    gap: 6px;
    min-height: 52px;
  }

  .scenic-recall-dialog .scenic-recall-palette button,
  .scenic-recall-dialog.is-sr-duel .scenic-recall-palette button {
    width: 50px !important;
    height: 50px !important;
    font-size: 22px;
  }
}
