/**
 * Mobile Panel Styles
 * ===================
 * Touch-feedback, safe-area, landscape, and high-contrast styles for the
 * mobile panel switcher. (Edge-swipe bounce/indicator styles removed with the
 * edge-swipe gestures in #6339 — the FAB switcher is the panel-access path.)
 */


/* ========================================
 * Touch Feedback States
 * ======================================== */

/* Active touch state on buttons */
@media (hover: none) and (pointer: coarse) {
  .mobile-panel-switcher__btn:active {
    transform: scale(0.95);
    background: var(--color-bg-elevated);
  }

  .mobile-panel-switcher__btn.active:active {
    transform: scale(0.95);
  }
}


/* ========================================
 * Safe Area Support (Notched Phones)
 * ======================================== */

@supports (padding: env(safe-area-inset-bottom)) {
  .mobile-panel-switcher {
    padding-bottom: calc(var(--space-2) + env(safe-area-inset-bottom, 0px));
  }

  /* Ensure modals don't get cut off */
  .mobile-mode .detail-modal,
  .mobile-mode .unified-modal {
    padding-bottom: env(safe-area-inset-bottom, 0px);
  }
}

/* ========================================
 * Landscape Orientation
 * ======================================== */

@media (orientation: landscape) and (max-height: 500px) {
  .mobile-panel-switcher {
    padding: 2px 8px;
  }

  .mobile-panel-switcher__btn {
    min-height: 36px;
    padding: 4px 12px;
    font-size: var(--font-size-sm);
  }

  .mobile-panel-switcher__icon {
    display: none; /* Hide icons in cramped landscape mode */
  }
}

/* ========================================
 * High Contrast Mode
 * ======================================== */

@media (prefers-contrast: high) {
  .mobile-panel-switcher__btn {
    border-width: 2px;
  }

  .mobile-panel-switcher__btn.active {
    border-color: white;
    outline: 2px solid white;
    outline-offset: 2px;
  }
}
/**
 * Mobile Bottom-Sheet Panel Overlay (#5123)
 * ==========================================
 * Non-narrative panels open as bottom-sheet overlays covering ~70vh.
 * The narrative behind remains visible at the top (~30vh).
 * Slides UP from the bottom (not from the side) to match native mobile patterns.
 * Panel content is unchanged; only the container changes.
 *
 * Only active on mobile (≤768px). Desktop is unaffected.
 * Input bar remains fixed at the bottom and is always visible (#5119).
 *
 * Z-index order (bottom → top):
 *   narrative base (z-panel 100) < backdrop (z-overlay 200) < sheet (z-sheet 300)
 *   < input-bar (z-sheet 300 + 1 = 301 via _input.css bump) < FAB (z-modal 400)
 *
 * (#6365 — corrected stale comment: the FAB uses --z-modal (400) per
 *  _mobile_fab.css, NOT --z-sticky, which is 10. Z-index tokens are
 *  single-valued in tokens/_typography.css; the old "conflicting token files"
 *  the mobile audit flagged at _generated.css were consolidated there.)
 *
 * Sheet geometry: height 70vh from bottom. Input bar (position:fixed, bottom:0)
 * occupies ~56px at the bottom of the viewport. The sheet sits ABOVE the input
 * bar in z-index order but its content area ends above the input bar in screen
 * space because the input bar is drawn over it.
 *
 * Z-index assignment:
 *   backdrop = --z-overlay (200): above panels, below sheet
 *   sheet    = --z-sheet   (300): above backdrop
 *   input    = --z-sheet   (300) at mobile — same layer BUT the input is declared
 *              AFTER the sheet in the cascade, so it paints on top. As a safety
 *              net the input.css rule is annotated to maintain this ordering.
 */

/* ========================================
 * Backdrop
 * Semi-transparent overlay behind the sheet, above the narrative
 * ======================================== */

.mobile-bottom-sheet-backdrop {
  display: none;
  position: fixed;
  inset: 0;
  background: var(--overlay-medium);
  z-index: var(--z-overlay);  /* 200 — above panels (100), below sheet (300) */
  opacity: 0;
  transition: opacity 0.25s ease;
  -webkit-tap-highlight-color: transparent;
}

.mobile-bottom-sheet-backdrop.open {
  opacity: 1;
}

/* ========================================
 * Bottom-Sheet Overlay (~70vh, slides up from bottom)
 * The sheet covers ~70% of the screen; ~30% of narrative is visible above.
 * The fixed input bar sits visually BELOW the sheet (below 30vh from bottom).
 * ======================================== */

.mobile-bottom-sheet {
  display: none;
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  /* 70vh covers most of the screen while leaving narrative strip visible above.
     Use dvh (dynamic viewport height) on Safari to account for browser chrome. */
  height: 70vh;
  height: 70dvh;
  /* Sheet sits above backdrop (z-overlay 200). Input bar also at z-sheet (300)
     but paints on top via cascade order — see _input.css annotation. */
  z-index: var(--z-sheet);  /* 300 */
  /* Start off-screen below, translate up to reveal */
  transform: translateY(100%);
  transition: transform 0.25s ease;
  background: var(--color-bg-primary);
  border-radius: var(--radius-xl) var(--radius-xl) 0 0;  /* Rounded top corners */
  box-shadow: 0 -4px 24px var(--overlay-medium);
  overflow: hidden;
  flex-direction: column;
  /* Safe area: bottom padding for notched phones (home indicator) */
  padding-bottom: env(safe-area-inset-bottom, 0px);
}

.mobile-bottom-sheet.open {
  transform: translateY(0);
}

/* #6341 — when the soft keyboard is open, contract the sheet by the keyboard
 * height so its lower region (search/notes/textarea) isn't hidden behind the
 * keyboard. Bottom lifts above the keyboard; height shrinks to keep the top
 * edge fixed. The scrollable __content (overflow-y:auto) + the focusin
 * scrollIntoView fallback in mobile_keyboard_manager then bring the focused
 * field into view. --mobile-keyboard-height is set by the keyboard manager. */
.mobile-keyboard-open .mobile-bottom-sheet {
  bottom: var(--mobile-keyboard-height, 0px);
  height: calc(70dvh - var(--mobile-keyboard-height, 0px));
}

/* Swipe-down-to-close: JS sets --swipe-offset (positive = moving down toward closed) */
.mobile-bottom-sheet.swiping {
  transition: none;
  transform: translateY(var(--swipe-offset, 0px));
}

/* ========================================
 * Sheet Header
 * Drag handle + title + close button at the top of the bottom sheet.
 * Tapping the header row OR the back button dismisses the sheet.
 * ======================================== */

.mobile-bottom-sheet__back-header {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  background: var(--color-bg-secondary);
  border-bottom: 1px solid var(--color-border-default);
  flex-shrink: 0;
  /* Visual height stays compact (36px) but tap target is 44px via padding */
  min-height: 44px;
  border-radius: var(--radius-xl) var(--radius-xl) 0 0;
  -webkit-tap-highlight-color: transparent;
}

.mobile-bottom-sheet__back-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  min-width: 44px;
  min-height: 44px;
  background: transparent;
  border: none;
  border-radius: var(--radius-md);
  color: var(--color-accent-primary);
  font-family: var(--font-mono);
  font-size: var(--font-size-sm);
  cursor: pointer;
  transition: background var(--transition-fast);
  -webkit-tap-highlight-color: transparent;
  user-select: none;
  -webkit-user-select: none;
}

.mobile-bottom-sheet__back-btn:active {
  background: var(--color-bg-tertiary);
  transform: scale(0.96);
}

.mobile-bottom-sheet__back-arrow {
  font-size: var(--font-size-lg);
  line-height: 1;
}

.mobile-bottom-sheet__panel-title {
  flex: 1;
  font-family: var(--font-mono);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ========================================
 * Drag Handle
 * Visible affordance above the header to indicate bottom-sheet dismissal.
 * Tapping it (44px touch target via min-height) triggers closeBottomSheet().
 *
 * #12595 (A11Y-14): the comment above claimed a 44px touch target, but the
 * actual box was padding (var(--space-2) 0 var(--space-1) = 8px + 4px) plus
 * the 4px ::after pill = 16px total — the same "visual size stays compact,
 * tap target is 44px via min-height" pattern already used correctly by
 * .mobile-bottom-sheet__back-header just above this in the cascade. Fixed
 * the same way: min-height: 44px + flex centering, so the visible pill stays
 * 36x4px but the actual clickable/tappable box meets the WCAG floor.
 * ======================================== */

.mobile-bottom-sheet__handle {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 0;
  cursor: pointer;
  flex-shrink: 0;
  /* The ::after pseudo creates the visual pill */
}

.mobile-bottom-sheet__handle::after {
  content: '';
  display: inline-block;
  width: 36px;
  height: 4px;
  background: var(--color-text-disabled);
  border-radius: var(--radius-sm);
  opacity: 0.5;
}

/* ========================================
 * Panel Content
 * Scrollable area for the panel content
 * ======================================== */

.mobile-bottom-sheet__content {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  min-height: 0;
  -webkit-overflow-scrolling: touch;
  /* #6361 — keep scroll inside the sheet; without this, hitting the top/bottom
   * chains to <body> and re-arms pull-to-refresh, and a reload mid-turn drops
   * the WebSocket. */
  overscroll-behavior-y: contain;
  /* #6365 — body.mobile-sheet-open sets touch-action:none to lock the page
   * behind the sheet; re-enable vertical pan here so the sheet content itself
   * stays scrollable on touch. */
  touch-action: pan-y;
  /* #11950 — scroll-space for the input bar that is drawn OVER this element.
   *
   * The file header above (and #5119) already record that the input bar is
   * deliberately above the sheet at z-index 301, and the sheet's own geometry
   * comment already acknowledges that "its content area ends above the input
   * bar in screen space because the input bar is drawn over it" — but nothing
   * compensated for it. With `flex:1; overflow-y:auto` and no bottom padding,
   * scrolling to the very end still leaves the final ~56px of EVERY panel under
   * the bar, and a tap there hits the input, not the panel. Any panel whose
   * primary action sits at the bottom of its content was unreachable on a
   * phone.
   *
   * The fix is padding, not a z-index swap — reordering would re-break #5119.
   * `--mobile-input-bar-h` is the input bar's MEASURED height, published on the
   * sheet element by openBottomSheet/openPanelFullscreen
   * (lib/mobile_panel_bottom_sheet.js), so this tracks a two-line input, a
   * larger root font-size, or a taller safe-area inset instead of pinning a
   * constant that drifts. The 3.5rem fallback only applies before the first
   * measurement. Over-reserving is harmless here (a little extra scroll); the
   * bug is exclusively under-reserving. */
  padding-bottom: var(--mobile-input-bar-h, 3.5rem);
}

/* Ensure panels inside the overlay fill it properly.
   #9862 dropped the dead `.split-panel` member — openBottomSheet() moves a bare
   `.grid-panel` node into the sheet. */
.mobile-bottom-sheet__content .grid-panel {
  display: flex;
  flex: 1;
  opacity: 1;
  transform: none;
  min-height: 100%;
  /* #12656 (PAN-14) — the sheet's __content is `overflow-x: hidden`, so any
   * panel wider than the sheet (~375px phone) is CLIPPED with no way to reach
   * the cut-off region. Eight registry panels carry `min_width: 400`
   * (room_graph, notice_board, lobby_browser, content_browser, world_selector,
   * quest_composer, session_prep_wizard, workspace_frame) and their content is
   * authored to that floor. Pin the moved-in panel to the sheet's width and
   * neutralise any inherited min-width floor so the content REFLOWS to the
   * available width instead of overflowing. Reflow beats horizontal scroll on
   * a phone (the PAN-14 recommendation), and the `.grid-panel` base is already
   * `min-width: 0` — this makes that true for the wide-content panels too,
   * scoped to the bottom-sheet context so the desktop split layout (where
   * min_width: 400 is legitimate) is untouched. */
  width: 100%;
  max-width: 100%;
  min-width: 0;
}

/* Belt-and-suspenders: keep the panel's OWN content from establishing an
   intrinsic width past the sheet. Direct children reflow to 100% rather than
   forcing the panel wider than the (overflow-x: hidden) __content can show.
   Kept to direct children so deeply-nested tables/grids that genuinely need
   their own horizontal scroll region (`overflow-x: auto` on an inner element)
   still work. */
.mobile-bottom-sheet__content .grid-panel > * {
  max-width: 100%;
}

/* #9862: the `.mobile-bottom-sheet__content .split-child` rule that stood here
   (added by #5964) never applied — openBottomSheet() moves the bare `.grid-panel`
   node into the sheet, never a wrapper (see the #9784 note in
   lib/mobile_panel_bottom_sheet.js). The `.mobile-bottom-sheet__content
   .grid-panel` rule directly above is the one that does the fill. */

/* Injected content from inline panel pop-out */
.mobile-bottom-sheet__injected {
  padding: var(--space-4);
  min-height: 100%;
}

/* Hide panel headers inside overlay (the back header is enough) */
.mobile-bottom-sheet__content .grid-panel__header {
  display: none;
}

/* ========================================
 * Only display on mobile phones (≤768px)
 * Tablet/desktop use the full split-panel layout and do not need bottom sheets.
 * ======================================== */

@media (max-width: 767px) {
  .mobile-bottom-sheet {
    display: flex;
  }

  /* Backdrop: always present in DOM for transition continuity but MUST NOT
     block touch events when closed. Without pointer-events:none, the invisible
     backdrop (opacity:0, position:fixed, inset:0) intercepts ALL taps (#1268). */
  .mobile-bottom-sheet-backdrop {
    display: block;
    pointer-events: none;
  }

  .mobile-bottom-sheet-backdrop.open {
    pointer-events: auto;
  }
}

@media (min-width: 768px) {
  .mobile-bottom-sheet,
  .mobile-bottom-sheet-backdrop {
    display: none !important;
  }
}

/* ========================================
 * HUD z-index suppression while sheet is open (#6358)
 *
 * Mobile-HUD panels sit at --z-floating-above (1001) which is above the
 * bottom sheet (--z-sheet: 300) and its backdrop (--z-overlay: 200). When
 * the sheet is open the HUD rows bleed through the top of the sheet, leaving
 * an un-dimmed strip. Lowering HUD panels to --z-panel-chrome (150) — below
 * the backdrop — while the sheet is open puts them behind both the scrim and
 * the sheet itself, removing the strip without affecting any other layout.
 *
 * body.mobile-sheet-open is added in openBottomSheet / openPanelFullscreen
 * and removed (after the 300ms transition) in closeBottomSheet.
 * ======================================== */

@media (max-width: 767px) {
  body.mobile-sheet-open .floating-panel--mobile-hud {
    z-index: var(--z-panel-chrome);  /* 150 — below backdrop (200) + sheet (300) */
  }

  /* #6365 — lock body scroll while the sheet is open. overscroll-behavior on
   * the sheet content (#6361) stops scroll-CHAINING, but a touch that lands
   * outside the sheet content (on the backdrop, or the narrative peeking above
   * the sheet) still scrolls <body> behind the sheet. position:fixed +
   * overflow:hidden on the body is the reliable cross-browser scroll-lock for
   * iOS Safari, which ignores `overflow:hidden` alone. The class is toggled by
   * openBottomSheet / openPanelFullscreen / closeBottomSheet (#6358). */
  body.mobile-sheet-open {
    overflow: hidden;
    overscroll-behavior: none;
    touch-action: none;
  }
}

/* ========================================
 * Reduced Motion
 * ======================================== */

@media (prefers-reduced-motion: reduce) {
  .mobile-bottom-sheet {
    transition: none;
  }

  .mobile-bottom-sheet-backdrop {
    transition: none;
  }
}
/**
 * Hamburger Menu - Mobile Escape Hatches
 * =======================================
 * Slide-out navigation menu for mobile users providing quick access
 * to Settings, Help, Profile, Tech Support, and Return to Lobby.
 *
 * Hidden on desktop (>=768px). Slides in from the right edge. Shown on
 * mobile and tablet portrait (<=767px, includes iPad portrait).
 */

/* ========================================
 * Hamburger Trigger Button
 * ======================================== */

/* #11949 — the trigger's box is published so that anything which must not be
 * drawn over it can compute where it ends without re-typing 8px/40px. The
 * mobile-HUD overlay row (floating_panel/_overlays.css) is the consumer: it is
 * z-index 1001 and the trigger is 410, so no z-order can put the trigger on top
 * — the HUD has to start below `inset + size` instead. The trigger is the only
 * mobile escape hatch (and the only route to the lobby campaigns sidebar), so a
 * hardcoded copy of these two numbers drifting is a trap-the-player bug. */
:root {
  --hamburger-trigger-inset: var(--space-2);
  --hamburger-trigger-size: 40px;
}

.hamburger-menu__trigger {
  display: none;
  position: fixed;
  top: var(--hamburger-trigger-inset);
  right: var(--space-2);
  right: calc(var(--space-2) + env(safe-area-inset-right, 0px));
  z-index: calc(var(--z-modal) + 10);
  width: var(--hamburger-trigger-size);
  height: var(--hamburger-trigger-size);
  padding: 0;
  border: 1px solid var(--color-border-default);
  border-radius: var(--radius-md);
  background: var(--color-bg-secondary);
  color: var(--color-text-primary);
  font-size: var(--font-size-2xl);
  line-height: 1;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  align-items: center;
  justify-content: center;
  transition: background var(--transition-fast),
              border-color var(--transition-fast);
}

.hamburger-menu__trigger:hover,
.hamburger-menu__trigger:active {
  background: var(--color-bg-elevated);
  border-color: var(--color-accent-primary);
}

.hamburger-menu__trigger:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

.hamburger-menu__trigger[aria-expanded="true"] {
  background: var(--color-bg-elevated);
  border-color: var(--color-accent-primary);
}

/* ========================================
 * Backdrop Overlay
 * ======================================== */

.hamburger-menu__backdrop {
  display: none;
  position: fixed;
  inset: 0;
  /* #2089: Explicit fallback ensures full-screen dark backdrop even if
     --overlay-heavy token is missing or unresolved. */
  background: var(--overlay-heavy);
  z-index: calc(var(--z-modal) + 11);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--duration-normal, 0.2s) ease;
  -webkit-tap-highlight-color: transparent;
  /* Backdrop blur adds depth separation between menu and content */
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
}

.hamburger-menu__backdrop--open {
  opacity: 1;
  pointer-events: auto;
}

/* ========================================
 * Slide-out Panel
 * ======================================== */

.hamburger-menu__panel {
  display: none;
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: 280px;
  max-width: 85vw;
  z-index: calc(var(--z-modal) + 12);
  background: var(--color-bg-primary);
  border-left: 1px solid var(--color-border-default);
  transform: translateX(100%);
  transition: transform var(--duration-normal) var(--ease-out);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding-right: env(safe-area-inset-right, 0px);
  flex-direction: column;
}

.hamburger-menu__panel--open {
  transform: translateX(0);
}

/* ========================================
 * Panel Header
 * ======================================== */

.hamburger-menu__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-4) var(--space-4);
  padding-top: calc(var(--space-4) + env(safe-area-inset-top, 0px));
  border-bottom: 1px solid var(--color-border-subtle);
}

.hamburger-menu__title {
  font-family: var(--font-mono);
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-primary);
  margin: 0;
}

.hamburger-menu__close {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: none;
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--color-text-muted);
  font-size: var(--font-size-2xl);
  cursor: pointer;
  transition: color var(--transition-fast),
              background var(--transition-fast);
}

.hamburger-menu__close:hover {
  color: var(--color-text-primary);
  background: var(--color-bg-hover);
}

.hamburger-menu__close:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

/* ========================================
 * Menu Items
 * ======================================== */

.hamburger-menu__items {
  list-style: none;
  margin: 0;
  padding: var(--space-2) 0;
}

.hamburger-menu__item {
  margin: 0;
  padding: 0;
}

.hamburger-menu__item-btn {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  padding: var(--space-3) var(--space-4);
  border: none;
  background: transparent;
  color: var(--color-text-primary);
  font-family: var(--font-mono);
  font-size: var(--font-size-base);
  text-align: left;
  cursor: pointer;
  transition: background var(--transition-fast),
              color var(--transition-fast);
  -webkit-tap-highlight-color: transparent;
}

.hamburger-menu__item-btn:hover,
.hamburger-menu__item-btn:active {
  background: var(--color-bg-hover);
}

.hamburger-menu__item-btn:focus-visible {
  outline: none;
  box-shadow: inset var(--focus-ring);
}

.hamburger-menu__item-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  color: var(--color-text-secondary);
}

.hamburger-menu__item-icon svg {
  width: 18px;
  height: 18px;
}

.hamburger-menu__item-label {
  flex: 1;
  min-width: 0;
}

/* Separator between groups */
.hamburger-menu__separator {
  height: 1px;
  background: var(--color-border-subtle);
  margin: var(--space-2) var(--space-4);
}

/* #12881: the .hamburger-menu__item-btn--danger rules were deleted — #12602
   (ded500b945) removed the hamburger's Return to Lobby item (breadcrumb is the
   canonical site), leaving the modifier with no producer. */

/* Warning items (Restart Character Creation) */
.hamburger-menu__item-btn--warning {
  color: var(--color-accent-gold, #f0a500);
}

.hamburger-menu__item-btn--warning .hamburger-menu__item-icon {
  color: var(--color-accent-gold, #f0a500);
}

/* Room-conditional items: hidden by default, JS reveals when in matching room */
[data-room-visible] {
  display: none;
}

[data-room-visible].hamburger-menu__item--visible {
  display: list-item;
}

/* ========================================
 * Mobile-only Visibility
 * ======================================== */

/* #6365 — breakpoint at 767px for mobile breakpoint consistency. The rest of the
 * layout treats <767px as mobile (via max-width: 767px rules). */
@media (max-width: 767px) {
  /* #16285 — the trigger sits INSIDE the status bar's row. The bar is
   * `--mobile-status-bar-h` (28px, _critical.css) tall on phones, but the
   * trigger was `top: 8px; height: 40px` — its box ran from 8px to 48px, 20px
   * below the bar, over the "Keep your character" banner and the narrative
   * header (prod-play 2026-09-19, 390x844). Re-deriving the two published
   * tokens (rather than re-typing the trigger's geometry) keeps every consumer
   * honest: floating_panel/_overlays.css computes the mobile-HUD row's top edge
   * from `inset + size`, which now equals the bar's own height, so the HUD
   * starts exactly under the bar instead of 20px lower. */
  :root {
    --hamburger-trigger-inset: 0px;
    --hamburger-trigger-size: var(--mobile-status-bar-h, 28px);
  }

  .hamburger-menu__trigger {
    display: flex;
    /* Height follows the bar (token above); the width stays a 40px target so
     * the glyph keeps its visual weight.
     *
     * `!important`, deliberately, on the four box properties: on a real phone
     * (pointer: coarse) three touch-target floors outrank this (0,1,0) rule —
     * `button:not(.tab-btn):not(.chip):not(.badge)` (0,3,1) and
     * `button[aria-label]:not([aria-label=""])` (0,2,1, padding 12px) in
     * terminal_2.css, `button` under (hover: none) in
     * base/keyboard_navigation.css — and `min-height` beats `height`, so the
     * painted box grew to 44px and hung 16px under the 28px bar. That is the
     * production screenshot (the token said 40; the phone showed 44).
     * Measured 2026-09-20 under Playwright's mobile-android / mobile-webkit
     * projects: computed height 44px, padding 12px, from those rules. The
     * 44px tap floor those rules exist for is kept by the ::before hit area
     * below, not by the painted box — so this is the one control that may
     * opt out of them, and the box must be pinned where no later floor can
     * re-grow it. */
    width: 40px !important;
    min-width: 40px !important;
    height: var(--hamburger-trigger-size) !important;
    min-height: var(--hamburger-trigger-size) !important;
    padding: 0 !important;
    font-size: var(--font-size-xl);
    border-radius: var(--radius-sm);
  }

  /* WCAG 2.5.5 tap floor: a 28px-tall visual box would be under 44px, so a
   * transparent ::before extends the HIT area to 44x44 without changing what
   * is painted (the same .nf-btn / entry-action pattern). */
  .hamburger-menu__trigger::before {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 44px;
    height: 44px;
    transform: translate(-50%, -50%);
  }

  /* The bar keeps the trigger's lane free: its actions zone scrolls
   * horizontally (#13528), and without this reservation the rightmost toolbar
   * button could sit under the fixed trigger. (0,2,0) in terminal_mobile.css,
   * which loads after terminal.css, so it outranks the (0,2,0)
   * `.mobile-bottom-sheet-mode .status-bar { padding: 2px 8px }` shorthand in
   * status_bar/_modes.css by order. */
  .terminal-container .status-bar {
    padding-right: calc(40px + var(--space-2) + var(--space-2) + env(safe-area-inset-right, 0px));
  }

  .hamburger-menu__backdrop {
    display: block;
  }

  .hamburger-menu__panel {
    display: flex;
  }
}

/* Desktop: ensure everything stays hidden */
@media (min-width: 768px) {
  .hamburger-menu__trigger,
  .hamburger-menu__backdrop,
  .hamburger-menu__panel {
    display: none;
  }
}

/* ========================================
 * Reduced Motion
 * ======================================== */

@media (prefers-reduced-motion: reduce) {
  .hamburger-menu__panel {
    transition: none;
  }

  .hamburger-menu__backdrop {
    transition: none;
  }

  .hamburger-menu__trigger {
    transition: none;
  }

  .hamburger-menu__item-btn {
    transition: none;
  }
}
/*
 * Terminal D&D - Mobile-Critical Stylesheet
 * ==========================================
 * Standalone bundle for mobile-specific components. Loaded as its own <link>
 * in terminal.html.erb so mobile users receive this CSS immediately after
 * terminal_2.css.
 *
 * Phase 0 of the CSS remediation plan (#5550). The Phase 1 brace-balance
 * truncation fix (#5551) restored _mobile_accessibility_fixes to terminal_2.css,
 * so it no longer lives here. The three mobile component partials below are
 * kept in this bundle as they are legitimately mobile-first components.
 *
 * Components included:
 *   _mobile_panel             — swipe-gesture animation + panel nav dots
 *   _mobile_bottom_sheet      — bottom-sheet overlay (≤768px only)
 *   _hamburger_menu           — slide-out nav menu (mobile escape hatches)
 *
 * Note: _mobile_accessibility_fixes now lives at the end of terminal_2.css
 * (restored by #5551). This bundle must still load AFTER terminal.css and
 * terminal_2.css (relies on CSS custom properties defined in _tokens.css).
 *
 * ⚠️  ORDERING: This bundle must be loaded AFTER terminal.css and terminal_2.css
 *     in the layout (it relies on CSS custom properties defined in _tokens.css).
 *
 * Layers on: terminal — the sentence above, in the form bin/checks/css_bundles.mjs
 *     reads (#15539): a token used here is checked against the terminal bundle.
 */




