/* ============================================================================
   MPI Scholar Academy — mobile pass
   BUILD m19

   Loaded LAST in every page's <head>, after that page's own <style> block, so
   these rules win on equal specificity. Nothing here changes desktop: every
   rule is inside a phone media query except the safe-area padding, which
   resolves to 0 on a device with no notch.

   Companion documents: mobile-study.md (measurements), mobile-practice-study.md
   (the standards these rules implement).
   ========================================================================= */


/* ---------------------------------------------------------------- 1. iOS zoom
   Safari force-zooms the page when a focused field is under 16px and never
   zooms back out. Every field goes to 16px at phone width. */
@media (max-width: 900px){
  input:not([type=range]):not([type=checkbox]):not([type=radio]),
  textarea, select, [contenteditable="true"]{ font-size: 16px !important }
}


/* ------------------------------------------------------- 2. The sound toggle
   Built in sfx.js with an inline style attribute, so overriding it needs
   !important. On a phone it becomes a 44px circle — the icon only — and lifts
   clear of whatever bottom furniture the room has. */
@media (max-width: 900px){

  /* Works whether or not sfx.js has been updated.
     Base: reposition and tighten the pill — this alone clears the collisions. */
  #sfx-toggle{
    padding: .6em .8em !important;
    font-size: .68rem !important; letter-spacing: .08em !important;
    right: calc(10px + env(safe-area-inset-right, 0px)) !important;
    bottom: calc(10px + env(safe-area-inset-bottom, 0px)) !important;
  }

  /* If sfx.js HAS been updated, the label sits in a <span class="lbl"> and the
     button can collapse to a 44px circle. If sfx.js has NOT been updated, this
     block simply never matches and the pill above is used instead. */
  #sfx-toggle:has(.lbl){
    width: 44px !important; height: 44px !important;
    padding: 0 !important; border-radius: 50% !important;
    display: flex !important; align-items: center; justify-content: center;
    font-size: 1.05rem !important; letter-spacing: 0 !important;
  }
  #sfx-toggle .lbl{ display: none }
}


/* ==========================================================================
   ROOM 01 — math.html
   ======================================================================= */
@media (max-width: 900px){

  /* The grid is 627px wide inside a 335px scroller. It pans — but the row and
     column headings scrolled away with it. Freeze both edges. */
  body:has(#grid) .gridwrap{
    max-height: 72vh; max-height: 72svh;
    overflow: auto; -webkit-overflow-scrolling: touch;
    padding: 0 0 24px;
  }
  body:has(#grid) #grid tr:first-child th{ position: sticky; top: 0; z-index: 3 }
  body:has(#grid) #grid tr th:first-child{ position: sticky; left: 0; z-index: 2 }
  body:has(#grid) #grid tr:first-child th:first-child{ z-index: 4 }

  /* Controls to the 44px target. */
  body:has(#grid) .wrap select,
  body:has(#grid) .wrap .btn{ min-height: 44px }

  /* The sound circle sits in the corner; keep the last row clear of it. */
  body:has(#grid) .gridwrap{ scroll-padding-bottom: 56px }
}


/* ==========================================================================
   ROOM 02 — python.html
   The phone drawer and the tap-to-insert library already work. Only the
   editor type size and the library targets need lifting.
   ======================================================================= */
@media (max-width: 900px){
  body:has(#codeview) #code{ font-size: 16px !important; line-height: 26px !important }
  body:has(#codeview) .lib button{ min-height: 40px; padding-top: .5em; padding-bottom: .5em }
  body:has(#codeview) #deskToggle{ min-height: 44px }
  body:has(#codeview) .deck > section.pane{
    padding-bottom: env(safe-area-inset-bottom, 0px);
  }
}


/* ==========================================================================
   ROOM 03 — xyz.html
   Measured collisions at 375px: #viewbar over #side 115x141, #top over #side
   200x49, #pad over #side 200x44, sound pill over #pad. The five fixed panels
   were laid out for a desktop column that does not exist on a phone. Stack
   them instead: title, view buttons, readout, keypad.
   ======================================================================= */
@media (max-width: 900px){
  body:has(#pad) #top{
    left: 8px; right: 8px;
    top: calc(8px + env(safe-area-inset-top, 0px));
    padding: 8px 128px 8px 12px;  /* right gutter reserves the sound button */
    gap: 10px;
  }
  body:has(#pad) #top .why,
  body:has(#pad) #top .sub{ display: none }
  /* if sfx.js was updated the button is a 44px circle and needs less gutter */
  body:has(#pad):has(#sfx-toggle .lbl) #top{ padding-right: 62px }
  /* the eight level chips wrapped to three rows (94px); one scrolling row */
  body:has(#pad) #top .chips{ flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch;
               max-width: 100%; padding-bottom: 2px }
  body:has(#pad) #top .chips button{ flex: 0 0 auto }

  /* View buttons become ONE horizontal row under the title bar. They wrapped
     to three rows (106px tall) and ran into the readout. */
  body:has(#pad) #viewbar{
    left: 8px; right: 8px; top: 132px; bottom: auto;
    flex-direction: row; flex-wrap: nowrap; justify-content: flex-start;
    overflow-x: auto; -webkit-overflow-scrolling: touch;
    gap: 8px; padding: 6px 8px;
  }
  body:has(#pad) #viewbar button{ min-height: 40px; padding: .5em .9em; white-space: nowrap; flex: 0 0 auto }

  /* The readout sits below the view row and above the keypad, and scrolls
     inside itself rather than growing into either. */
  body:has(#pad) #side{
    left: 8px; right: 8px; top: 190px; bottom: auto;
    width: auto; padding: 12px 14px;
    max-height: calc(100vh - 190px - 268px);
    max-height: calc(100svh - 190px - 268px);
    overflow: auto; -webkit-overflow-scrolling: touch;
  }

  /* Keypad keeps the bottom, clear of the home indicator. */
  body:has(#pad) #pad{
    left: 8px; right: 8px; width: auto;
    bottom: calc(8px + env(safe-area-inset-bottom, 0px));
    padding: 12px;
  }
  body:has(#pad) #pad button{ min-height: 44px }

  /* The android is decorative and was landing on the readout. */
  body:has(#pad) #mate,
  body:has(#pad) #mateSay{ display: none }

  /* No clear gap exists between the readout and the keypad on a 667px screen,
     so the sound circle docks into the title bar's reserved right gutter. */
  body:has(#pad) #sfx-toggle{
    top: calc(12px + env(safe-area-inset-top, 0px)) !important;
    bottom: auto !important; height: 44px !important;
    right: 14px !important;
  }
}


/* ==========================================================================
   ROOM 04 — race.html
   BLOCKER: #dock is a fixed 343px-wide flex row whose contents measure 452px,
   with overflow:visible and body overflow-x:hidden — so the Race button sat at
   x 376-469 on a 375px screen with no way to scroll to it. The room could not
   be finished on a phone. The dock now wraps.
   ======================================================================= */
@media (max-width: 900px){
  body:has(#dock) #dock{
    left: 8px; right: 8px; transform: none; max-width: none;
    bottom: calc(8px + env(safe-area-inset-bottom, 0px));
    flex-wrap: wrap; justify-content: center; gap: 8px;
    padding: 10px 12px;
  }
  body:has(#dock) #dock #verdict{
    flex: 1 1 100%; text-align: center; font-size: .78rem; line-height: 1.35;
  }
  body:has(#dock) #dock .btn{ min-height: 44px }

  /* The hint line sat where the dock's second row now lives. */
  body:has(#dock) #hint{ bottom: calc(160px + env(safe-area-inset-bottom, 0px)) }

  /* Phase chips were 32x32. */
  body:has(#dock) .chip{ width: 44px; height: 44px; border-radius: 12px }

  /* Racks and dashboard stop short of the taller dock. */
  body:has(#dock) #bankPanel{ max-height: calc(100vh - 118px - 168px); max-height: calc(100svh - 118px - 168px) }
  body:has(#dock) #dash{ max-height: calc(100vh - 118px - 227px); max-height: calc(100svh - 118px - 227px); overflow: auto }

  body:has(#dock) #sfx-toggle{ bottom: calc(168px + env(safe-area-inset-bottom, 0px)) !important }
}


/* ==========================================================================
   ROOM 05 — fractions.html
   #bar grows to 360px tall at phone width and ran 31px into #cubes.
   ======================================================================= */
@media (max-width: 900px){
  body:has(#cubes) #bar{
    max-height: min(44vh, calc(100vh - 350px));
    max-height: min(44svh, calc(100svh - 350px));
    overflow-y: auto; -webkit-overflow-scrolling: touch;
  }
  /* Given-column chips and page tabs were 24-25px tall. The chooser that is
     actually rendered on a phone uses .gv without .btn. */
  body:has(#cubes) #bar .btn,
  body:has(#cubes) #linebar .btn,
  body:has(#cubes) .gv{ min-height: 40px; padding: .5em 1em }
  body:has(#cubes) .val{ min-height: 40px }
}


/* ==========================================================================
   ROOM 06 — reading.html
   #dots had `top` set in the phone media query and `bottom:8px` re-applied by
   a later base rule, so it stretched 233px down the screen and sat on top of
   the story text (115x160) and the writing panel (115x29). Release the bottom
   edge so it is a row of dots again.
   ======================================================================= */
@media (max-width: 900px){
  body:has(#storyText) #dots{
    bottom: auto !important;
    height: auto !important;
    align-items: center;
  }

  /* The writing panel opened 34px tall at the very bottom. Give it room by
     trimming the story pane. */
  body:has(#storyText) #story{ height: 22vh; height: 22svh }
  body:has(#storyText) #write{
    top: calc(var(--bar, 74px) + var(--bandh) + 22vh + 18px);
    bottom: calc(8px + env(safe-area-inset-bottom, 0px));
    min-height: 180px;
  }
  body:has(#storyText) #write textarea{ min-height: 96px }

  /* Page tabs were 25px, page-turn arrows 30px. */
  body:has(#storyText) #bar .btn,
  body:has(#storyText) .pgbar .btn{ min-height: 40px }
  body:has(#storyText) .turn{ min-width: 44px; min-height: 44px; justify-content: center }

  /* Parts-of-speech labels are the tap-to-select path on touch — make them
     comfortable. */
  body:has(#storyText) #tagBox .tag{ min-height: 40px; padding: .5em .9em }
  body:has(#storyText) #pSentence .tok{ padding: .18em .12em }
}


/* ==========================================================================
   ROOM 07 — music.html
   Panels already tile correctly. Only the flute holes and the drum need a
   larger touch area, and the canvas must not fight the page gesture.
   ======================================================================= */
@media (max-width: 900px){
  body:has(#keys) #stage{ touch-action: none }

  /* The title bar wrapped to 244px and the question panel opened inside it. */
  body:has(#keys) #bar{ max-height: 108px; overflow-y: auto; -webkit-overflow-scrolling: touch }
  body:has(#keys) #bar .sub{ display: none }
  body:has(#keys) #ask{ top: 128px }
  body:has(#keys) #keys button{ min-width: 44px; min-height: 44px }
  body:has(#keys) #drumPanel button{ min-height: 44px }
  body:has(#keys) #keys{ bottom: calc(14px + env(safe-area-inset-bottom, 0px)) }
}


/* ==========================================================================
   LANDING PAGE — index.html
   ======================================================================= */
@media (max-width: 900px){
  body:has(#curtain) .modeswitch button,
  body:has(#curtain) .seg button{ min-height: 44px }
  body:has(#curtain) footer .home{ display: inline-block; min-height: 44px; line-height: 44px }
}


/* ==========================================================================
   SHSAT TABLES
   shsat-table-wide.html overflowed the phone by 153px and
   shsat-table-horizontal.html by 510px; neither file had a single media query.
   Give the table a scroll container of its own instead of letting it push the
   page sideways, and freeze the first column.
   ======================================================================= */
@media (max-width: 900px){
  /* These two are periodic-table layouts of .cube tiles, not <table> markup.
     html and body were both overflow-x:hidden, so 153px (wide) and 510px
     (horizontal) of tiles were clipped off the right edge with no way to
     reach them. Let the document pan sideways instead of clipping. */
  html.shsat-doc, html.shsat-doc body{
    overflow-x: auto !important; -webkit-overflow-scrolling: touch;
  }
}


/* ==========================================================================
   PHONE OPERATING LAYER  (mobile.js) — tab bar, sheets, number pad
   Active only when mobile.js has attached (body.mui) at phone width.
   ======================================================================= */
@media (max-width: 900px){

  /* --- the tab bar -------------------------------------------------- */
  #mtabs{
    position: fixed; z-index: 1200;
    left: 8px; right: 8px;
    bottom: calc(6px + env(safe-area-inset-bottom, 0px));
    display: flex; gap: 8px;
  }
  .mtab{
    flex: 1 1 0; min-height: 48px;
    border-radius: 14px; border: 2px solid rgba(0,0,0,.25);
    background: #23203A; color: #fff;
    font: 700 .8rem/1 system-ui, sans-serif; letter-spacing: .06em;
    box-shadow: 0 4px 14px rgba(0,0,0,.35);
  }
  .mtab.mon{ background: #F5C244; color: #3A2A00 }

  /* --- a sheet ------------------------------------------------------ */
  body.mui .msheet{
    position: fixed !important;
    top: auto !important; left: 8px !important; right: 8px !important;
    bottom: calc(62px + env(safe-area-inset-bottom, 0px)) !important;
    width: auto !important; max-width: none !important;
    max-height: 58vh !important; max-height: 58svh !important;
    overflow: auto !important; -webkit-overflow-scrolling: touch;
    margin: 0 !important;
    transform: translateY(130%) !important;
    transition: transform .22s ease !important;
    z-index: 1150 !important;
    pointer-events: auto !important;
  }
  body.mui .msheet.mopen{ transform: none !important }

  /* --- the number pad ----------------------------------------------- */
  #mpad{
    position: fixed; z-index: 1300;
    left: 0; right: 0;
    bottom: 0; padding: 8px 8px calc(8px + env(safe-area-inset-bottom, 0px));
    display: none; grid-template-columns: repeat(4, 1fr); gap: 7px;
    background: rgba(20,18,31,.96);
    border-top: 2px solid rgba(255,255,255,.14);
  }
  #mpad.mopen{ display: grid }
  .mkey{
    min-height: 52px; border-radius: 12px;
    border: 1px solid rgba(255,255,255,.18);
    background: #2E2A46; color: #fff;
    font: 700 1.25rem/1 system-ui, sans-serif;
  }
  .mkey:active{ background: #4A4463 }
  .mkey.mok{ grid-column: span 2; background: #4E9A51 }
  .mkey.mback{ background: #6E3B3B }
  /* while the pad is up: tabs hide, a closed sheet stays closed, and the
     open sheet (which holds the answer boxes) rises to sit on the pad */
  body.mpad-open #mtabs{ display: none }
  body.mpad-open .msheet.mopen{
    bottom: calc(212px + env(safe-area-inset-bottom, 0px)) !important;
    max-height: 42vh !important; max-height: 42svh !important;
  }

  /* --- rooms give the freed screen back to the scene ---------------- */

  /* xyz: the old fixed slots for #side and #pad no longer apply — they are
     sheets now. The view row drops to just under the slim title bar. */
  body.mui:has(#inX) #side, body.mui:has(#inX) #pad{ height: auto }
  body.mui:has(#inX) #viewbar{ top: 76px }
  body.mui:has(#inX) #top{ padding-right: 62px }
  body.mui:has(#inX) #sfx-toggle{
    top: calc(12px + env(safe-area-inset-top, 0px)) !important;
    bottom: auto !important; height: 44px !important;
  }

  /* race: the dock rides just above the tab bar; hint above the dock */
  body.mui:has(#dock) #dock{ bottom: calc(64px + env(safe-area-inset-bottom, 0px)) }
  body.mui:has(#dock) #hint{ bottom: calc(216px + env(safe-area-inset-bottom, 0px)) }
  body.mui:has(#dock) #sfx-toggle{ bottom: calc(224px + env(safe-area-inset-bottom, 0px)) !important }

  /* fractions: with the control panel in a sheet, the cube and the number
     lines climb to the top of the screen */
  body.mui:has(#cubes) #cubes{ top: calc(10px + env(safe-area-inset-top, 0px)) !important; bottom: auto !important }
  body.mui:has(#cubes) #linebar{ bottom: calc(64px + env(safe-area-inset-bottom, 0px)) !important }
  body.mui:has(#cubes) #coach{ bottom: calc(64px + env(safe-area-inset-bottom, 0px)) }

  /* reading: menu and desk are sheets, so the band and the story split the
     screen between them */
  body.mui:has(#storyText) #band{ top: calc(10px + env(safe-area-inset-top, 0px)) }
  body.mui:has(#storyText) #story{
    height: auto;
    top: calc(10px + env(safe-area-inset-top, 0px) + var(--bandh, 150px) + 10px);
    bottom: calc(64px + env(safe-area-inset-bottom, 0px));
  }
  body.mui:has(#storyText) #dots{
    top: auto !important;
    bottom: calc(64px + env(safe-area-inset-bottom, 0px)) !important;
  }

  /* music: keys ride above the tab bar; score tucks above the keys */
  body.mui:has(#drumPanel) #keys{ bottom: calc(64px + env(safe-area-inset-bottom, 0px)) }
  body.mui:has(#drumPanel) #score{ bottom: calc(154px + env(safe-area-inset-bottom, 0px)) }
}

@media (max-width: 900px){
  /* fractions: the number-line drag heads float above everything by design —
     while a sheet or the pad is up they hover over it and steal the taps */
  body.mui.msheet-open:has(#cubes) .lhead,
  body.mui.mpad-open:has(#cubes) .lhead,
  body.mui.msheet-open:has(#cubes) #coach,
  body.mui.mpad-open:has(#cubes) #coach{ visibility: hidden }
}

@media (max-width: 900px){
  /* fractions: the table panel is a flex column (header + rows). As a sheet it
     needs a real height or the rows area collapses to nothing. */
  body.mui:has(#cubes) #drill.msheet{
    display: flex !important; flex-direction: column;
    height: 56vh !important; height: 56svh !important;
  }
  body.mui:has(#cubes) #drill.msheet #rows{ flex: 1 1 auto; min-height: 0 }
  /* while the pad is up the table shortens to sit on top of it */
  body.mui.mpad-open:has(#cubes) #drill.msheet{
    height: 36vh !important; height: 36svh !important;
  }
}

@media (max-width: 900px){
  /* Room 01: while the pad is up, the document gets bottom headroom equal to
     the pad's height and the grid scroller shortens — so the LAST line of the
     table can rise above the pad instead of being trapped under it. */
  body.mui.mpad-open{ padding-bottom: calc(250px + env(safe-area-inset-bottom, 0px)) }
  body.mui.mpad-open:has(#grid) .gridwrap{
    max-height: calc(100vh - 320px);
    max-height: calc(100svh - 320px);
  }
  body.mui:has(#grid) .gridwrap{ scroll-padding-bottom: 12px }
}


/* ==========================================================================
   m18 — the playfield owns the screen: title bars are one slim line on a
   phone; the explanation text lives in the sheets, not on top of the room.
   ======================================================================= */
@media (max-width: 900px){
  body.mui #top .sub, body.mui #top .why, body.mui #bar .sub, body.mui #top .stamp{ display: none }
  body.mui:has(#dock) #top{ padding: 8px 12px; gap: 8px }
  body.mui:has(#dock) #top .chips{ flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch; max-width: 100% }
  body.mui:has(#dock) #top .chips .chip{ flex: 0 0 auto }
  /* race dock: the verdict line only takes space when it has something to say */
  body.mui:has(#dock) #dock #verdict:empty{ display: none }
  body.mui:has(#dock) #dock{ padding: 8px 10px; gap: 6px }
  /* xyz: with the chips gone the bar is back-link + title */
  body.mui:has(#inX) #top{ padding: 8px 62px 8px 12px; min-height: 0 }
  body.mui:has(#inX) #viewbar{ top: 64px }
  body.mui:has(#inX) #side .chips{ display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 10px }
  /* python: the mission sheet holds the back link and the goal text */
  body.mui:has(#codeview) #focusbar.msheet{ padding: 14px 16px; font-size: .95rem; line-height: 1.4 }
  body.mui:has(#codeview) #focusbar.msheet #focusGoal{ display: block }
  body.mui:has(#codeview) #deskToggle{ top: calc(10px + env(safe-area-inset-top, 0px)) }
}
@media (max-width: 900px){
  /* python: the code drawer ends above the tab bar, so the last line and the
     status line are never under it */
  body.mui:has(#codeview) .pane:has(#code){ padding-bottom: calc(62px + env(safe-area-inset-bottom, 0px)) }
}

@media (max-width: 900px){
  /* Room 01: the room opens on the table, not on a page of text */
  body.mui:has(#grid) header.top{ padding: 8px 0 6px }
  body.mui:has(#grid) header.top .numrain{ display: none }
  body.mui:has(#grid) header.top h1{ font-size: 1.25rem; margin: 2px 0 0 }
  body.mui:has(#grid) header.top p{ display: none }
  body.mui:has(#grid) .controls{ gap: 6px; margin: 8px 0 }
  body.mui:has(#grid) .meter{ margin: 6px 0 }
  body.mui:has(#grid) #msettings{ background: #fff; border-radius: 16px; padding: 14px 16px;
    display: flex; flex-direction: column; gap: 10px; font: 600 .95rem system-ui, sans-serif; color: #23203A }
  body.mui:has(#grid) #msettings p{ display: block; font-weight: 500; font-size: .9rem; line-height: 1.4; color: #4B4570; margin: 0 0 6px }
  body.mui:has(#grid) #msettings select{ min-height: 44px; font-size: 16px }
  body.mui:has(#grid) #msettings .btn{ min-height: 46px }
  body.mui:has(#grid) #probPage{ margin-top: 6px }
}

@media (max-width: 900px){
  /* Room 01 Problems page: the first problem lands on the first screen */
  body.mui:has(#grid) .probhead h2{ display: none }
  body.mui:has(#grid) .probhead{ gap: 6px; margin: 0 0 8px }
  body.mui:has(#grid) .probhead .seg{ flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch; max-width: 100% }
  body.mui:has(#grid) .probhead .seg button{ flex: 0 0 auto; white-space: nowrap }
  body.mui:has(#grid) #probShow, body.mui:has(#grid) #probNew{ display: none }   /* they live in the tab bar */
  body.mui:has(#grid) .mtab-act{ display: none }
  body.mui:has(#grid)[data-page="prob"] .mtab-act, body.mui:has(#grid)[data-page="md"] .mtab-act{ display: block }
  body.mui:has(#grid) .prob{ padding: 12px 12px 14px }
  body.mui:has(#grid) .prob .kind{ margin-bottom: 4px }
  body.mui:has(#grid) #probDemo .pdemocard{ margin-bottom: 10px }
}
@media (max-width: 900px){
  /* reading: the story arrows sit ON the picture band, above the story panel,
     one under each thumb */
  body.mui:has(#storyText) .turn{ z-index: 1000; top: calc(10px + env(safe-area-inset-top, 0px) + var(--bandh, 150px) / 2) }
  /* race: the dock with the Race button rides above the parts sheet, so Race
     is never hidden behind the rack */
  body.mui:has(#dock) #dock{ z-index: 1160 }
}
