/* ──────────────────────────────────────────────────────────────────
   css/builder-mobile.css
   2026-05-13 — phone-viewport (≤480px) fixes for the Board Builder.

   PROBLEM (user report):
     "won't preview, it's not responsive, the design is not able to
      be used on a mobile device."

   AUDIT FINDINGS — what was BROKEN at ≤480px before this file:

     1. Tile grid columns at cols-5 / cols-6 produced sub-50px tiles
        on a 360px viewport. Settings → Grid Columns lets a user (or
        a synced desktop save) set cols=6, then the phone renders
        microscopic, un-tappable tiles. The saved `cols` value is
        correct on tablet/kiosk — it's the phone surface that needs
        to clamp down. This is a DISPLAY rule only — board.cols on
        disk is preserved.

     2. Hamburger (.topbar-hamburger) was 36×36px — below WCAG 2.5.5
        and Apple HIG 44×44 tap-target floor. wave7-mobile.css
        ratchets .topbar-btn up but missed the hamburger specifically.

     3. Props panel as bottom-sheet at ≤1024px slid up correctly but
        the bottom edge clipped under the iPhone notch / home
        indicator (no `env(safe-area-inset-bottom)` padding). Users
        with a notched device lost the Done button at the bottom.

     4. Sidebar drawer at ≤480px was 280px wide — on a 360px
        viewport that's 78% of the screen. With `max-width:80vw`
        already in place, this is borderline OK but the inner board
        list squeezed templates and QR off-screen on portrait phones.
        Tighten the inner accordion max-heights so all three
        sections (Boards / Templates / QR) co-exist.

     5. .editor-toolbar at ≤640px wraps but the grid-N buttons can
        crush together. Force flex-wrap and ensure each toolbar-btn
        meets 44×44 floor on mobile.

     6. .props-image-results grid was 3 fixed columns — fine at
        360px, but on the narrowest viewports (≤340px) cells become
        un-scannable. Switch to auto-fill with min 70px.

     7. Editor area horizontal scroll risk: .editor-toolbar has
        max-width:680px — if a button forces the row wider than the
        viewport on a 320px screen, body scrolls horizontally. Pin
        editor-area overflow-x:hidden so no descendant can leak.

     8. .tile font-size: emoji is 2.2rem and label is 0.7rem
        regardless of viewport — fine for cols 1-3, tight for cols
        4-5. Scale emoji to 1.7rem at narrow widths.

   NON-GOALS (intentionally NOT touched):
     • The saved board data model — capping cols is CSS-only.
     • Drag-and-drop logic — touch-interactions.js already polyfills
       HTML5-DnD via long-press + ghost drag (Tier 1 mobile parity,
       2026-05-02). That solution is already shipped; this file just
       locks the visual side.
     • Preview button behavior — events.js opens use.html in a new
       tab and that works on mobile.

   LABEL: PILOT-READY. Requires iOS Safari + Android Chrome hardware
   verification before PRODUCTION-READY. Loaded LAST in the cascade
   so its rules win over builder.css / wave7-mobile.css / responsive-
   topbar.css for the narrow-viewport overrides below.
────────────────────────────────────────────────────────────────── */

/* ── 1. Cap effective columns at 4 on phones (display-only) ────── */
/* The saved board.cols value can be 5 or 6 (set via Settings →
   Grid Columns, or synced from a tablet/desktop session). On a
   360px viewport, cols-5 produces ~55px tiles and cols-6 produces
   ~45px tiles — both un-tappable for the AAC users the builder
   serves (motor-impaired, low-vision, fine-motor-developing). We
   override the grid-template-columns on the .tile-grid only at
   ≤480px so the SAME board renders correctly on phone preview,
   tablet edit, and kiosk run. JS does NOT mutate board.cols. */
@media (max-width: 480px) {
  .tile-grid.cols-5,
  .tile-grid.cols-6 {
    grid-template-columns: repeat(4, 1fr);
  }
  /* 2026-05-26 (Luke caught): Grid 5/6 toolbar buttons did NOTHING
     visually on mobile because of the cap above — JS updated
     board.cols but CSS forced visual layout back to 4. User taps
     '5', screen doesn't change, looks broken.
     Fix: hide buttons that produce no visual change at this width
     so every visible Grid button delivers a real layout flip. */
  .editor-toolbar [data-cols="5"] { display: none !important; }
}
/* xs phones (≤360px, iPhone SE 1st gen): cap at 3 cols so a
   .cols-4 saved board still has tappable tiles. cols-1/2/3 are
   already fine. */
@media (max-width: 360px) {
  .tile-grid.cols-4,
  .tile-grid.cols-5,
  .tile-grid.cols-6 {
    grid-template-columns: repeat(3, 1fr);
  }
  /* Same no-op rationale: Grid 4 also identical to Grid 3 at this
     narrowest band, so hide both 4 and 5. (5 already hidden above.) */
  .editor-toolbar [data-cols="4"] { display: none !important; }
}

/* ── 2. Hamburger tap-target floor (WCAG 2.5.5) ─────────────── */
/* builder.css defines .topbar-hamburger as 36×36; bump to 44×44
   on the mobile band where it's actually visible. flex centering
   already in place. Margin-right to keep visual breathing room
   from the brand block. */
@media (max-width: 1024px) {
  .topbar-hamburger {
    width: var(--tap-target-min, 44px);
    height: var(--tap-target-min, 44px);
    min-width: var(--tap-target-min, 44px);
    min-height: var(--tap-target-min, 44px);
    font-size: 1.35rem;
  }
}

/* ── 3. Props panel bottom-sheet: iPhone safe-area + handle ──── */
/* At ≤1024px builder.css makes .props-panel a bottom sheet
   (transform: translateY 100% → 0). It DOES NOT respect the home-
   indicator safe area on iPhone X+ / 14 Pro / 15 Pro — content
   was being cut off by the system gesture bar. Padding-bottom
   uses env() with a px fallback so older browsers degrade. The
   inner scroll container also needs the extra room. */
@media (max-width: 1024px) {
  .props-panel {
    padding-bottom: env(safe-area-inset-bottom, 0);
  }
  .props-inner {
    /* Existing max-height:75vh remains. Pad bottom inside the
       scroll container so the last Done / Delete buttons clear the
       home indicator without users having to swipe. */
    padding-bottom: calc(1.5rem + env(safe-area-inset-bottom, 0));
  }
  /* Surface the swipe handle that mobile-tokens.css ships at the
     top of the props sheet so users learn "you can swipe me down"
     by recognition. The handle div has zero width on desktop. */
  .props-panel.open .props-inner::before {
    content: "";
    display: block;
    width: var(--sheet-handle-w, 40px);
    height: var(--sheet-handle-h, 4px);
    background: rgba(0, 0, 0, 0.2);
    border-radius: 999px;
    margin: 0.25rem auto 0.75rem;
  }
}

/* ── 4. Sidebar drawer: tighten inner accordion heights ────────── */
/* At ≤480px the sidebar is 80vw (~288px on 360px viewport). The
   board list + templates + QR accordion all want vertical space.
   Tighten each so all three remain reachable without scrolling
   the rail. The .sidebar-scroll wrapper still scrolls if the
   total overflows. */
@media (max-width: 480px) {
  .sidebar-acc-body .sidebar-list {
    max-height: 28vh;
  }
  .sidebar-acc-body .sidebar-templates {
    max-height: 30vh;
  }
  /* QR sized down so the copy-link button stays visible above the
     fold on a 640-720px short-viewport phone. */
  .sidebar-deploy-qr {
    width: 160px;
    height: 160px;
  }
}

/* ── 5. Editor toolbar: 44×44 floor on the grid-N row + spacing ─ */
/* The toolbar already wraps at ≤640px via builder.css. Lock the
   button height to 44px (was ~32px after the existing shrink
   rule) and give the row some breathing room so the wrapped
   second-row buttons don't collide. */
@media (max-width: 768px) {
  .editor-toolbar {
    flex-wrap: wrap;
    gap: 0.4rem;
    row-gap: 0.5rem;
    max-width: 100%;
  }
  .editor-toolbar .toolbar-btn {
    min-height: var(--tap-target-min, 44px);
    min-width: var(--tap-target-min, 44px);
    /* The grid 1/2/3/4/5 buttons specifically — they were the
       most cramped. Pad horizontally so digits don't collide
       with the button edge. */
  }
  .editor-toolbar-group {
    flex-wrap: wrap;
  }
}

/* ── 6. Image search results: responsive grid ─────────────────── */
/* The 3-column fixed grid (builder.css line ~401) is fine at
   360px but at ≤320px (oldest devices, some PWA installs) cells
   drop below 60px and become un-scannable. Auto-fill with a 70px
   min gives 4 cols at 360px and 3 cols at 320px without us
   writing two media queries. */
@media (max-width: 480px) {
  .props-image-results {
    grid-template-columns: repeat(auto-fill, minmax(70px, 1fr));
  }
}

/* ── 7. Horizontal overflow guard ─────────────────────────────── */
/* body { overflow:hidden } is set globally (builder.css line 33)
   so body itself can't scroll horizontally. But descendants
   (.editor-area, .app-layout) CAN if a child overflows. Belt-and-
   suspenders: clamp them on phone. This catches the case where a
   long board name or an emoji-heavy toolbar pushes the row past
   the viewport edge. */
@media (max-width: 768px) {
  .app-layout {
    overflow-x: hidden;
    max-width: 100vw;
  }
  .editor-area {
    overflow-x: hidden;
    max-width: 100%;
  }
  /* The tablet frame inherits but make it explicit — it has its
     own width:100% but a chunky padding can push content past. */
  .tablet-frame {
    max-width: 100%;
    overflow: hidden;
  }
}

/* ── 8. Tile sizing at narrow widths ──────────────────────────── */
/* Default tile emoji is 2.2rem (~35px). At cols-4 on a 360px
   viewport each tile is ~75-80px wide; emoji at 35px is fine.
   At cols-3 on a 320px viewport, tile is ~95px wide — emoji
   should be 1.7rem so the label has room beneath without
   stretching the tile vertically. Min-height drops slightly too
   so the grid doesn't sprawl off-screen vertically (the editor
   area scrolls but the user shouldn't HAVE to scroll for a
   12-tile board). */
@media (max-width: 480px) {
  .tile {
    min-height: 80px;
  }
  .tile-emoji {
    font-size: 1.7rem;
  }
  .tile-label {
    font-size: 0.65rem;
  }
  /* (visibility-only — see (hover:none) block below for the full
     touch-usability treatment: ≥44px hit area + :active feedback.
     This 0.85 default is retained so the layout looks correct on
     phone-sized screens even with a stylus or other hover-capable
     pointer attached.) */
  .tile-delete {
    opacity: 0.85;
  }
}

/* ── 8b. Tile delete button — TOUCH-USABLE on any hover-less device ──
   Codex stop-time review caught: making .tile-delete *visible* on
   phones (block 8 above) was not the same as making it *usable*. The
   base style at builder.css line 336 ships:
     - 20×20px tap target — well under the WCAG 2.5.5 Target Size (AA)
       floor of 44×44px
     - :hover{background:var(--fk-neg)} for visual feedback — :hover
       never fires on a pure-touch input, so the user gets zero
       confirmation that a tap registered
   `(hover: none)` is the correct query for "this input mode cannot
   hover" — fires on iPhone Safari, Android Chrome, iPad without
   trackpad, and any tablet/phone form factor — but does NOT fire on
   a Surface or iPad-with-Magic-Keyboard where the user has a real
   hover-capable cursor. That's the right behavior: a trackpad user
   on a 10" tablet still wants the desktop's hover-to-reveal model. */
@media (hover: none) {
  .tile-delete {
    /* Visible affordance — slightly larger than desktop's 20×20 so
       the icon is readable at arm's length, but still small enough
       not to crowd the tile content. */
    width: 32px;
    height: 32px;
    font-size: 0.9rem;
    opacity: 0.85;
  }
  /* Expand the effective tap target to ≥44×44 without growing the
     visible chrome — a transparent pseudo-element overlay extends
     the hit zone 8px in every direction (32 + 16 = 48px, comfortably
     above the WCAG floor). Position absolute is safe because the
     parent .tile-delete is itself position:absolute already. */
  .tile-delete::before {
    content: "";
    position: absolute;
    inset: -8px;
    /* No background — purely a hit-area expansion. */
  }
  /* Tap feedback. :hover never fires on touch; :active does. Mirror
     the desktop :hover background swap + add a subtle scale so the
     user sees + feels (combined with iOS haptic) that the tap
     registered before navigation/state change. */
  .tile-delete:active {
    background: var(--fk-neg, #c44);
    transform: scale(0.92);
    opacity: 1;
  }
}

/* ── 9. Topbar dropdowns: open as bottom-sheet on phone ──────── */
/* The Students / Device dropdowns open as small positioned panels
   anchored to their trigger. At ≤480px the panel can fall off the
   right edge and clip. Force max-width and right-align with a
   small viewport padding. */
@media (max-width: 480px) {
  .topbar-dropdown-panel {
    max-width: calc(100vw - 1rem);
    right: 0.5rem !important;
    left: auto !important;
  }
}

/* ── 10. Preview surface on phone ─────────────────────────────── */
/* The Preview button opens /use.html?preview=1 in a new tab.
   On phones, some browsers throttle window.open after a delay —
   add a visual cue so users know the button worked even before
   the new tab pops. The button already has a 44px floor from
   editor-toolbar above; here we give it a slight highlight so
   it stands out among 4 toolbar buttons on a small screen. */
@media (max-width: 480px) {
  #previewBtn {
    background: var(--amber-light, #F5C563);
    color: var(--ink, #1A1A2E);
    font-weight: 700;
  }
  #previewBtn:hover {
    background: var(--amber, #E8A838);
  }
}

/* ── 11. Mobile topbar polish (2026-05-14 audit) ──────────────── */
/* Three issues spotted at 390×844 in the cloud-sync wave puppeteer
   audit:
     • Cloud-sync pill text ("💾 Local only") collided with the
       avatar / Sign In cluster on the right edge. JS now
       abbreviates to icon-only ≤480 (see cloud-sync-pill.js
       abbreviate()) — this CSS just tightens the inline padding so
       the pill sits flush among the other compact controls.
     • #boardNameInput took 110px+ of horizontal space showing
       "Untitled Board" placeholder text the user already sees in
       big type below. Shrink it to a 96px stub that still allows
       rename via tap-to-expand on focus. Browsers honor the input
       width attr; we just clamp the visual.
     • Props panel ✕ + image-picker ✕ were 28×28 + free-padding
       (rendered as 36×44 / 27×44). Push both to 44×44 explicit so
       any future text/icon change can't shrink them below the
       WCAG 2.5.5 floor again. */
@media (max-width: 480px) {
  #cloudSyncPill {
    /* JS still owns colors + text — only re-tune the box on phone */
    padding: 4px 6px !important;
    margin: 0 4px !important;
    font-size: 13px !important;
    line-height: 1 !important;
    min-width: 28px;
    text-align: center;
  }
  #boardNameInput {
    /* Keep editable, just visually compact. Focus state still
       enlarges via builder.css default behavior. */
    max-width: 96px;
    flex-shrink: 1;
  }
  .props-close,
  .image-picker-close {
    width: var(--tap-target-min, 44px) !important;
    height: var(--tap-target-min, 44px) !important;
    min-width: var(--tap-target-min, 44px);
    min-height: var(--tap-target-min, 44px);
    /* Keep visual 28px circle but grow the hit area. The pseudo-
       element trick used for .tile-delete is unnecessary here —
       the buttons sit in their own row so growing the visible box
       won't crowd siblings. */
    font-size: 1rem;
  }
}

/* ── 12. Login screen polish ──────────────────────────────────── */
/* "Sign up" + "Forgot password?" rendered as 100×14 / 101×36 —
   both below the WCAG 44×44 floor. Pad them up without growing
   the visual chrome by extending the hit area. */
@media (max-width: 480px) {
  .login-card a {
    min-height: var(--tap-target-min, 44px);
    display: inline-block;
    padding: 0.5rem 0.25rem;
    line-height: 1.4;
  }
}

/* ── 13. Topbar overflow audit (2026-05-19) ───────────────────────
   Puppeteer responsive audit at 375 / 768 caught the topbar children
   overlapping each other when there were 9+ pills crammed into a
   fixed-row flex container. Symptoms (mobile):
     • "credentials" pill clipped past the right edge at 375px
     • "Practice" + "My credentials" + "Local only" overlapping each
       other at 768px
   The .topbar height is locked to var(--topbar-h) (60px) because the
   app-layout downstream uses calc(100vh - var(--topbar-h)). So we
   can't wrap to multi-row — instead we (a) hide non-essential pills
   at narrow widths, (b) condense brand subtitle, (c) allow horizontal
   scroll as a final overflow safety net so nothing ever clips silently. */
@media (max-width: 768px) {
  .topbar {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    /* Hide the scrollbar — touch scroll is invisible by default;
       keyboard-only users get the hamburger menu instead. */
    scrollbar-width: none;
  }
  .topbar::-webkit-scrollbar {
    display: none;
  }
  /* Brand subtitle ("Board Builder") duplicates the page title +
     eats horizontal budget. Hide on tablet/phone — the brand name
     alone is enough. */
  .topbar-brand-tag {
    display: none;
  }
  /* Worksheet is a low-frequency standalone — fold into the hamburger
     menu surface (which auto-includes hidden topbar items). */
  #worksheetBtn {
    display: none !important;
  }
  /* The vertical divider between brand and board-name input is pure
     decoration — collapses cleanly at narrow widths. */
  .topbar-divider {
    display: none;
  }
  /* 2026-05-19 (final-verify): the auto-injected ⋯ overflow-pinned
     menu stacks multiple pills (My credentials / Practice / Local
     only) on top of each other at tablet widths — they collide
     visually even though scrollWidth === clientWidth. The hamburger
     menu surfaces the same actions, so hide the redundant overlay
     across the entire <=768 range (this rule supersedes the older
     <=480 rule which was too narrow). */
  .topbar-overflow-pinned {
    display: none !important;
  }
}

/* ≤480 (phone): be more aggressive — guest mode pills, secondary
   dropdowns, and the user-info label all eat horizontal space that
   the brand + board-name + primary CTA need to stay tap-reachable.
   2026-05-19 (pass 2): verify smoke showed 195px overflow at 375 with
   "Guest" text + Sign Up + Sign In all chained. !important on the
   #userName hide because the avatar's container reasserts inline-
   flex display from the parent rule. */
@media (max-width: 480px) {
  /* Brand subtitle was already hidden at ≤768, but the .topbar-brand
     container still allocated 88px because "TinkySpeak" is bold at
     1.1rem. Shrink the brand name on phone so the parent collapses. */
  .topbar-brand-name {
    font-size: 0.95rem;
  }
  /* User text label ("Mrs. Johnson" / "Guest") next to the avatar —
     avatar alone is the identifier on phone. */
  .topbar-user #userName {
    display: none !important;
  }
  /* Students dropdown is teacher-focused; hide on phone (still
     reachable via the side panel / dashboard nav). */
  #topbarStudentsDD {
    display: none;
  }
  /* Compact Sign Up / Sign In: keep both visible (acquisition matters)
     but trim the padding so they fit without forcing scroll.
     2026-05-19 (final-verify): aggressive padding cut + acquisition
     edges trimmed so the pair fits in ~100px instead of 128. */
  #topbarSignUp,
  #topbarSignIn {
    padding: 0.35rem 0.5rem !important;
    font-size: 0.72rem !important;
  }
  #topbarSignUp {
    margin-right: 2px !important;
  }
  /* 2026-05-19 (Codex pass 5 verify-smoke): the topbar overflow audit
     showed that hiding #userName alone leaves the entire
     .topbar-user container at 49px (avatar + flex gap). When a guest
     is browsing, the dedicated Sign Up + Sign In buttons already
     identify the auth state — the avatar+name cluster is redundant
     real estate. Hide the whole thing under <=480, but keep it for
     authed users (whose name + avatar IS their identity). The
     :is selector lets the rule remain a single declaration. */
  .topbar-user {
    display: none;
  }
  /* The auto-injected ⋯ overflow-pinned menu (topbar-dropdowns.js)
     stacks ALL hidden topbar items into a single touch target. With
     studentsDD + worksheet + brand-tag + userName all hidden at this
     breakpoint, the overflow menu is now redundant for those items.
     Keep it visible only when there's something left to overflow. */
}

/* ≤414 (iPhone Pro and below): hide the redundant "Sign Up" pill —
   the login page itself surfaces a Sign Up link inline ("Don't have
   an account? Sign up"), so we keep only the primary Sign In CTA
   here. Saves ~75px (button + gap + margin) which closes most of
   the remaining overflow gap at 375. Brand also gets a final shrink. */
@media (max-width: 414px) {
  #topbarSignUp {
    display: none !important;
  }
  .topbar-brand-name {
    font-size: 0.85rem;
  }
  /* Shrink board-name input below the <=480 cap of 96px to 64px so
     the auth pill still fits without horizontal scroll on iPhone Pro
     and below. Need BOTH max-width AND min-width — the prior verify
     smoke showed an inherited min-width:80 was holding the box up
     even with max-width:64 applied. Focus state still opens it via
     builder.css behavior. */
  #boardNameInput {
    max-width: 64px !important;
    min-width: 64px !important;
    width: 64px !important;
  }
}

/* ≤360 (smallest supported phone): board-name input cap that already
   exists at 96px max-width still works; just make sure the input
   doesn't fight the Device dropdown for the same horizontal slot. */
@media (max-width: 360px) {
  #boardNameInput {
    max-width: 72px;
  }
  /* At this width, even the Device dropdown can hide — its actions
     (Download / Print / Push) all live in the Push modal that ALSO
     opens from the hamburger menu's "Push to Device" item. */
  .topbar-brand-tag,
  #topbarDeviceDD {
    display: none;
  }
}
