/* Spec 0132: mobile responsive pass across /app + /engineer.
 *
 * ADDITIVE ONLY. Every rule lives inside a mobile media query
 * (max-width: 767.98px) so desktop rendering at >= 768px viewport
 * is bit-identical to pre-slice output.
 *
 * Loaded on all 7 /app HTMLs and /engineer.html via a <link> tag
 * appended after app-shell.css.
 *
 * Layered:
 *   L1  Root shell        (appshell grid, main width, right rail stack)
 *   L2  Sidebar drawer    (widen drawer, safe-area insets)
 *   L3  Topbar            (compact, touch targets)
 *   L4  Main content pass (hero, tiles, cards, chip strips)
 *   L5  Right rail stack  (below main, not display:none anymore)
 *   L6  Modals            (full-screen sheets: equipment, project,
 *                          document upload/viewer, task, project detail,
 *                          onboarding, notification bell drawer)
 *   L7  Chat surface      (composer sticky, tiles single column,
 *                          floating panels safe)
 *   L8  Touch target hits (44x44 min on all buttons)
 *   L9  Typography scale  (base 15-16px, headings scaled)
 *
 * Break at 768px because iPad portrait is 768px and the desktop shell
 * with persistent sidebar kicks in at 1024px (see oem-dashboard.css
 * @media (min-width: 1024px)). The 768-1023px band remains "tablet-ish
 * desktop" per spec out-of-scope note.
 */

/* ═══════════════════════════════════════════════════════════════════
 * L1 · ROOT SHELL, mobile grid + rail stack
 * ═══════════════════════════════════════════════════════════════════
 * oem-dashboard.css @media (max-width: 900px) already collapses the
 * grid to 1fr and hides .appshell-rail. Spec acceptance criterion 4
 * says the right rail must STACK BELOW main content, not disappear.
 * Override that display:none and re-mount the rail as a full-width
 * row below main. Grid rows expand to auto to accommodate.
 * ═══════════════════════════════════════════════════════════════════ */
@media (max-width: 767.98px) {
  /* Round 12 · M-01 fix (2026-08-19). These tracks were `1fr`, which is
   * shorthand for `minmax(auto, 1fr)`. The `auto` MINIMUM means the track
   * cannot shrink below the largest min-content contribution among its
   * items, and .appshell-topbar is a flex row whose right cluster carries
   * the default min-width:auto (366.6px of un-shrinkable content). Result:
   * the column resolved to 601px on a 375px viewport and every child,
   * .appshell-main included, inherited that width. Because html/body/
   * .appshell all set overflow-x:hidden, the excess was clipped rather
   * than scrollable, so ~60% of every /app surface was unreachable and
   * documentElement.scrollWidth still read 375 — which is why six mobile
   * passes and the responsive sweep all reported clean.
   *
   * minmax(0, 1fr) sets the floor to zero so the track follows the
   * viewport. The min-width:0 rules below let the topbar's flex children
   * actually shrink once the track stops propping them open.
   *
   * Knock-on: this also fixes the oversized dashboard tiles (M-16).
   * .oemd-tiles is forced to a single column below 414px (L1, line ~159);
   * that column was filling the 601px track, so one tile rendered 570px
   * wide on a 375px screen. It now scales with the viewport. The
   * 2026-08-17 auto-fit change in oem-dashboard.css could not help here,
   * both because the !important single-column rule outranks it on mobile
   * and because the defect was the container, not the track definition. */
  .appshell {
    grid-template-columns: minmax(0, 1fr) !important;
    grid-template-rows: 56px auto auto !important;
  }
  .appshell:has(.appshell-app) {
    grid-template-columns: minmax(0, 1fr) !important;
  }
  .appshell-topbar {
    grid-column: 1 !important;
    grid-row: 1 !important;
    min-width: 0 !important;
  }
  /* Once the track above stops propping the topbar open at 601px, the
   * topbar becomes viewport-width and its cluster has to actually fit.
   * Two things are needed, and both are mechanical — nothing is hidden,
   * so no product decision is baked in here:
   *
   *   1. nowrap. Otherwise "Sign out" breaks onto two lines and the
   *      "Get the app" pill onto four, blowing the 56px topbar height.
   *   2. ellipsis on the two elastic text runs (vessel title, account
   *      name). A blanket min-width:0 on the children is NOT the answer:
   *      it lets .appshell-tb-title collapse to ~4px so the vessel name
   *      vanishes silently. Truncation degrades; collapse deletes. */
  .appshell-topbar,
  .appshell-tb-left,
  .appshell-tb-right {
    flex-wrap: nowrap !important;
  }
  .appshell-tb-left > *,
  .appshell-tb-right > *,
  .appshell-tb-identity > * {
    white-space: nowrap !important;
  }
  .appshell-tb-title {
    min-width: 0 !important;
    max-width: 34vw !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
    white-space: nowrap !important;
  }
  /* The identity chip is built in appshell.js:519 as exactly three
   * children, none of them classed:
   *   1  <span>PAID · </span>      plan state
   *   2  <span>full@email.addr</span>
   *   3  <button class="appshell-identity-reset">Sign out</button>
   * It measured 204px at 375, the widest elastic run in the cluster.
   *
   * Clamp child 2 ONLY. Clamping the container instead ellipses the
   * FIRST child, which turns the plan chip into "B…" and leaves the
   * email intact — precisely backwards. The email is the low-value run
   * on a phone; plan state and sign-out must stay legible.
   * The spans are inline, so they need inline-block for max-width and
   * text-overflow to apply at all. */
  .appshell-tb-identity {
    min-width: 0 !important;
  }
  .appshell-tb-identity > span:nth-child(2) {
    display: inline-block !important;
    max-width: 20vw !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
    white-space: nowrap !important;
    vertical-align: bottom !important;
  }
  .appshell-tb-identity > span:first-child,
  .appshell-identity-reset {
    flex-shrink: 0 !important;
  }
  .appshell-main {
    grid-column: 1 !important;
    grid-row: 2 !important;
    padding: 14px 14px 24px !important;
    max-width: 100% !important;
    overflow-y: visible !important;
    /* safe-area for notch phones */
    padding-left: max(14px, env(safe-area-inset-left)) !important;
    padding-right: max(14px, env(safe-area-inset-right)) !important;
  }
  .appshell-rail {
    /* Undo the display:none from oem-dashboard.css @media(max-width:900px)
     * so the rail sections stack below main content on mobile. */
    display: flex !important;
    grid-column: 1 !important;
    grid-row: 3 !important;
    position: static !important;
    height: auto !important;
    max-width: 100% !important;
    border-left: 0 !important;
    border-top: 1px solid var(--ymh-line, rgba(11,26,47,.08)) !important;
    padding: 16px 14px 24px !important;
    padding-left: max(14px, env(safe-area-inset-left)) !important;
    padding-right: max(14px, env(safe-area-inset-right)) !important;
    overflow: visible !important;
  }
  /* Rail section lists inside stack no longer need scroll. */
  .appshell-rail > div:not(.rail-photo):not(.rail-inspection):not(.rail-focus-care) > .rail-section-list,
  .appshell-rail > div:not(.rail-photo):not(.rail-inspection):not(.rail-focus-care) > .oemd-warranty-list {
    overflow-y: visible !important;
    max-height: none !important;
  }
  .appshell-rail > div:not(.rail-photo):not(.rail-inspection):not(.rail-focus-care) {
    overflow: visible !important;
  }
}

/* ═══════════════════════════════════════════════════════════════════
 * L2 · SIDEBAR DRAWER, widen + safe area
 * ═══════════════════════════════════════════════════════════════════ */
@media (max-width: 767.98px) {
  .appshell-sidebar {
    width: min(88vw, 340px) !important;
    padding: 14px 12px calc(12px + env(safe-area-inset-bottom)) !important;
    padding-left: max(12px, env(safe-area-inset-left)) !important;
  }
  /* Larger tap area for nav items in the drawer. */
  .appshell-nav-item,
  .appshell-hist-item {
    min-height: 44px !important;
    font-size: 14px !important;
    padding: 10px 12px !important;
  }
  .appshell-newchat,
  .appshell-vessel-switch,
  .appshell-logout {
    min-height: 44px !important;
    font-size: 14px !important;
  }
}

/* ═══════════════════════════════════════════════════════════════════
 * L3 · TOPBAR, compact, safe area
 * ═══════════════════════════════════════════════════════════════════ */
@media (max-width: 767.98px) {
  .appshell-topbar {
    height: 56px !important;
    padding: 0 8px !important;
    padding-left: max(4px, env(safe-area-inset-left)) !important;
    padding-right: max(8px, env(safe-area-inset-right)) !important;
  }
  .appshell-tb-title {
    font-size: 14px !important;
    /* keep visible; older rule hid it under 640 was gone but ensure show */
  }
  /* The 640px rule in oem-dashboard.css hides crumb + tb-chip. Preserve
   * that behavior on tiny phones; the "What can I ask?" chip is
   * still available inside the composer help affordances. */
  .appshell-burger {
    width: 44px !important;
    height: 44px !important;
  }
  .appshell-tb-cta {
    padding: 8px 12px !important;
    font-size: 12px !important;
    min-height: 40px !important;
  }
}

/* ═══════════════════════════════════════════════════════════════════
 * L4 · MAIN CONTENT, hero, tiles, chip strips, cards
 * ═══════════════════════════════════════════════════════════════════ */
@media (max-width: 767.98px) {
  /* Hero + greeting. */
  .app-hero-h1,
  .oemd-welcome-h {
    font-size: 22px !important;
    line-height: 1.25 !important;
    margin: 6px 0 6px !important;
  }
  .app-vessel-chip { font-size: 12.5px !important; }
  .app-cards-label { font-size: 13px !important; }
  .app-ask-divider { margin: 16px 0 10px !important; font-size: 11.5px !important; }

  /* Landing tiles: force single column and pad. oem-dashboard.css already
   * has a 720px breakpoint for this but the intra-tile layout stays too
   * wide on 375. Tighten. */
  /* Round 12 (2026-08-19): was a flat `1fr !important`, which forced one
   * column at every width below 768 and, before the M-01 track fix, let
   * that single column inherit the blown-out 601px container so one tile
   * rendered 570px wide on a 375px screen.
   *
   * Derive the count from the 260px tile minimum that oem-dashboard.css:356
   * already declares, instead of hard-coding it. min(260px, 100%) is the
   * guard that keeps a 260px floor from overflowing viewports narrower
   * than 260px. Result: 1-up on phones, 2-up from ~560px, and the 414px
   * two-column override below is no longer needed. */
  .oemd-tiles {
    grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr)) !important;
    gap: 8px !important;
  }
  .oemd-tile {
    padding: 12px !important;
    min-height: 68px !important;
  }
  .oemd-tile-title { font-size: 13.5px !important; }
  .oemd-tile-sub { font-size: 12px !important; }
  .oemd-tile-cta {
    padding: 8px 14px !important;
    min-height: 40px !important;
    font-size: 12.5px !important;
  }
  .oemd-tile-icon-pill { flex-shrink: 0 !important; }

  /* Mode chip row on chat surfaces, becomes horizontal scroller. */
  .oemd-mode-row {
    overflow-x: auto !important;
    flex-wrap: nowrap !important;
    padding-bottom: 4px !important;
    -webkit-overflow-scrolling: touch !important;
    scrollbar-width: none !important;
  }
  .oemd-mode-row::-webkit-scrollbar { display: none !important; }
  .oemd-mode {
    flex: 0 0 auto !important;
    min-height: 36px !important;
  }

  /* Any category / tab strip inside a page. Common patterns:
   * .ymh-cat-tabs, .ymh-doc-tabs, .ymh-proj-tabs, .ymh-eq-tabs,
   * .ymh-projects-tabs, plus generic role=tablist. Horizontal scroll. */
  .ymh-cat-tabs, .ymh-doc-tabs, .ymh-proj-tabs, .ymh-eq-tabs,
  .ymh-projects-tabs, .ymh-projects-view-switch,
  [role="tablist"] {
    overflow-x: auto !important;
    flex-wrap: nowrap !important;
    -webkit-overflow-scrolling: touch !important;
    scrollbar-width: none !important;
  }
  .ymh-cat-tabs::-webkit-scrollbar,
  .ymh-doc-tabs::-webkit-scrollbar,
  .ymh-proj-tabs::-webkit-scrollbar,
  .ymh-eq-tabs::-webkit-scrollbar,
  .ymh-projects-tabs::-webkit-scrollbar,
  .ymh-projects-view-switch::-webkit-scrollbar,
  [role="tablist"]::-webkit-scrollbar { display: none !important; }
  .ymh-cat-tabs > *,
  .ymh-doc-tabs > *,
  .ymh-proj-tabs > *,
  .ymh-eq-tabs > *,
  .ymh-projects-tabs > *,
  .ymh-projects-view-switch > *,
  [role="tablist"] > * {
    flex: 0 0 auto !important;
    white-space: nowrap !important;
    min-height: 40px !important;
  }
}

/* ═══════════════════════════════════════════════════════════════════
 * L5 · RIGHT RAIL, sizing when stacked below main
 * ═══════════════════════════════════════════════════════════════════ */
@media (max-width: 767.98px) {
  /* Hero photo slot pinned at 160px on mobile (down from 180 desktop). */
  .appshell-rail > .app-rail-hero-photo,
  .app-rail-hero-photo {
    height: 160px !important;
    min-height: 160px !important;
  }
  .rail-photo {
    height: 120px !important;
  }
  /* Rail sections: room to breathe below main content. */
  .appshell-rail > * {
    width: 100% !important;
  }
  .appshell-rail .rail-section-head {
    margin-top: 4px !important;
  }
  /* Focus-care CTA sits at the end of the mobile stack (not "auto"
   * pushed to bottom since column is content-height now). */
  .rail-focus-care {
    margin-top: 4px !important;
  }
}

/* ═══════════════════════════════════════════════════════════════════
 * L6 · MODALS, full-screen sheets on mobile
 * ═══════════════════════════════════════════════════════════════════
 * Modal container class names discovered via grep of /assets/*.js:
 *   .ymh-eq-modal          (equipment-form-modal.js)
 *   .ymh-doc-modal         (document-viewer-modal.js)
 *   .ymh-upload-modal      (document-upload-modal.js)
 *   .ymh-proj-modal        (project-form-modal.js)
 *   .ymh-projdetail-modal  (project-detail-modal.js)
 *   .ymh-task-modal        (task-form-modal.js)
 *   .ymh-onb-card          (onboarding-modal.js)
 *
 * Each uses inline styles for position/size but the class is unique so
 * we can win specificity with !important. Convert the centered card
 * into a full-viewport sheet that slides up from the bottom.
 * ═══════════════════════════════════════════════════════════════════ */
@media (max-width: 767.98px) {
  .ymh-eq-modal,
  .ymh-doc-modal,
  .ymh-upload-modal,
  .ymh-proj-modal,
  .ymh-projdetail-modal,
  .ymh-task-modal,
  .ymh-onb-card {
    top: 0 !important;
    left: 0 !important;
    right: 0 !important;
    bottom: 0 !important;
    width: 100vw !important;
    max-width: 100vw !important;
    height: 100vh !important;
    max-height: 100vh !important;
    max-height: 100dvh !important;
    border-radius: 0 !important;
    transform: none !important;
    padding: 20px 16px calc(20px + env(safe-area-inset-bottom)) 16px !important;
    padding-left: max(16px, env(safe-area-inset-left)) !important;
    padding-right: max(16px, env(safe-area-inset-right)) !important;
    padding-top: max(20px, env(safe-area-inset-top)) !important;
    overflow-y: auto !important;
    -webkit-overflow-scrolling: touch !important;
  }
  /* Onboarding-modal.js sets both an "on" class transform. Neutralize. */
  .ymh-onb-card-on {
    transform: none !important;
  }
  /* Close buttons: bump touch target. */
  .ymh-eq-close,
  .ymh-doc-close,
  .ymh-upload-close,
  .ymh-proj-close,
  .ymh-projdetail-close,
  .ymh-task-close,
  .ymh-onb-close {
    min-width: 44px !important;
    min-height: 44px !important;
    padding: 10px !important;
  }
  /* Two-column form grids collapse. Rely on natural grid-template but
   * many modal forms use inline style="grid-template-columns:1fr 1fr;".
   * Force single column at mobile for readability. */
  .ymh-eq-form div[style*="grid-template-columns"],
  .ymh-proj-modal div[style*="grid-template-columns"],
  .ymh-task-modal div[style*="grid-template-columns"] {
    grid-template-columns: 1fr !important;
  }
  /* Notification bell drawer (ymh-notifications.js opens a fixed panel).
   * Full-width on mobile so it does not overflow. */
  /* .ymh-notif-panel was the shared container, removed when the drawer
     moved into the topbar (see ymh-notifications.css). This rule has been
     matching nothing since. The live element is .appshell-notif-drawer and
     its mobile placement now lives beside its own base rule. */
}

/* ═══════════════════════════════════════════════════════════════════
 * L7 · CHAT SURFACE (engineer / app chat), composer + tiles + panels
 * ═══════════════════════════════════════════════════════════════════
 * engineer.css already pins the chat surface on <=900px when
 * body.eng-chatting is set. Extend for 375px specifics:
 *   - single-column tile grid (engineer.css hits at 480, redundant safe)
 *   - composer sticky at bottom (already handled by body.eng-chatting
 *     path but the neutral /app landing does not enter that state
 *     until first message; make composer usable pre-chat too)
 *   - floating oemd-panel-float overlays fit viewport
 * ═══════════════════════════════════════════════════════════════════ */
@media (max-width: 767.98px) {
  /* Chat container on app landing (before eng-chatting). */
  .oemd-chat.oemd-chat-hero {
    padding: 10px 4px !important;
  }
  .eng-thread {
    padding: 10px 0 !important;
  }
  .eng-msg {
    max-width: 96% !important;
    /* 15px, not 14px. The assistant reply is no longer a bubble with a
     * border to lean on, it is the reading surface, and 14px on a phone
     * for a five-line troubleshooting answer is a squint. */
    font-size: 15px !important;
    line-height: 1.62 !important;
  }
  .eng-input-wrap {
    /* The composer trio is pinned at 44px for touch, so the wrap padding
     * is the only height left to give back. 8px -> 5px. */
    padding: 5px 8px !important;
  }
  .eng-input {
    font-size: 16px !important; /* iOS: prevents zoom on focus */
    /* Round 12 · M-19. `flex: 1` without a zero min-width is the flex
     * form of the same defect as M-01: a flex item's default
     * min-width:auto stops it shrinking below its min-content, so at
     * 320px the input held its width and pushed #engSend 36px off the
     * screen. The composer's three 40px buttons are flex:none and
     * cannot yield, so the input is the only thing that can. */
    min-width: 0 !important;
  }
  .eng-mic, .eng-send, .eng-attach {
    width: 40px !important;
    height: 40px !important;
    min-width: 40px !important;
  }
  /* Floating help panels (Fault decoder, Photo diagnose). */
  .oemd-panel-float {
    left: 6px !important;
    right: 6px !important;
    bottom: 12px !important;
    width: auto !important;
    max-width: none !important;
    max-height: 78vh !important;
    max-height: 78dvh !important;
    overflow-y: auto !important;
    -webkit-overflow-scrolling: touch !important;
  }
  /* Suggestion tile grid inside chat. */
  .eng-cards { grid-template-columns: 1fr !important; }
  .eng-guide-tiles { grid-template-columns: 1fr !important; }
  /* Guide bubble float should not obstruct composer. */
  .eng-guide-float, .ymh-guide-bubble {
    bottom: calc(76px + env(safe-area-inset-bottom)) !important;
  }
}

/* ═══════════════════════════════════════════════════════════════════
 * L8 · TOUCH TARGETS, 44x44 minimum on all interactive
 * ═══════════════════════════════════════════════════════════════════
 * Applied narrowly to elements known to fall below the threshold.
 * Broad rule for buttons/anchors comes with too much collateral, so we
 * enumerate specifically. Anchor tag hit boxes rely on their padded
 * children in most cases. */
@media (max-width: 767.98px) {
  .rail-qa-row,
  .app-rail-profile-cta,
  .oemd-mode {
    min-height: 40px !important;
  }
  .rail-list-row {
    min-height: 44px !important;
    padding: 8px 10px !important;
  }
}

/* ═══════════════════════════════════════════════════════════════════
 * L9 · TYPOGRAPHY BASELINE
 * ═══════════════════════════════════════════════════════════════════
 * Slightly bump base font so 11-12px chrome text isn't unreadable on
 * dense phone pixel-densities. Scoped to app pages (data-shell-brand
 * or .appshell descendants) so we don't touch marketing.
 * ═══════════════════════════════════════════════════════════════════ */
@media (max-width: 767.98px) {
  .appshell,
  .appshell .rail-section-title {
    /* Section titles were 10.5px, keep uppercase readability. */
  }
  .rail-section-title {
    font-size: 11px !important;
  }
  .rail-list-row .t { font-size: 13px !important; }
  .rail-list-row .m { font-size: 11px !important; }
  .rail-qa-row { font-size: 13px !important; }
}

/* ═══════════════════════════════════════════════════════════════════
 * L10 · HORIZONTAL-SCROLL GUARD
 * ═══════════════════════════════════════════════════════════════════
 * Global belt-and-suspenders: prevent body horizontal scroll and any
 * appshell descendant from projecting past viewport. Acceptance #8. */
@media (max-width: 767.98px) {
  html, body { overflow-x: hidden !important; }
  .appshell, .appshell-main, .appshell-rail { overflow-x: hidden !important; }
}

/* ═══════════════════════════════════════════════════════════════════
 * Spec 0149 · Cannes mobile responsive polish pass
 * ═══════════════════════════════════════════════════════════════════
 * Adds additive polish on top of spec 0132 baseline. Targets three
 * breakpoints (375 / 414 / 768) called out in the spec. All rules are
 * scoped to max-width media queries so desktop rendering at >=1024px
 * is bit-identical.
 *
 * Layers:
 *   0149.L1  Chat compose safe area + dvh (spec Layer 2)
 *   0149.L2  Hero tile grid 2 col at 414, 1 col at 375 (Layer 2)
 *   0149.L3  Chat bubble max width 85vw at 375 (Layer 2)
 *   0149.L4  Kanban horizontal scroll <=640 (Layer 3)
 *   0149.L5  Filter pill row wrap + horizontal scroll (Layers 3-6)
 *   0149.L6  Card padding tighten 12px <=640 (Layer 3)
 *   0149.L7  Waitlist input/button stack at 375 (Layer 4)
 *   0149.L8  Calendar cell + monthnav touch targets (Layer 5)
 *   0149.L9  Equipment / documents list stack (Layers 6-7)
 *   0149.L10 Settings form full width + delete full width (Layer 8)
 *   0149.L11 Notification bell 44x44 + dropdown clip guard (Layer 9)
 *   0149.L12 Font-size floor 14px body, 12px chip (Layer 9)
 * ═══════════════════════════════════════════════════════════════════ */

/* 0149.L1 · CHAT COMPOSE SAFE AREA (Layer 2) --------------------------
 * The neutral /app landing keeps the composer inline until eng-chatting
 * fires. Once chatting, engineer.css pins the composer via body.eng-chatting.
 * Ensure the pinned composer respects iOS safe-area-inset-bottom and
 * uses dvh so the visual viewport shrink when the keyboard opens does
 * not clip the input row. */
@media (max-width: 767.98px) {
  body.eng-chatting .eng-input-wrap,
  .oemd-chat.oemd-chat-hero .eng-input-wrap {
    padding-bottom: calc(5px + env(safe-area-inset-bottom)) !important;
  }
  body.eng-chatting .oemd-chat,
  body.eng-chatting .eng-thread {
    min-height: 0 !important;
    max-height: 100dvh !important;
  }
  /* Guard against the compose bar being pushed off-screen by 100vh
   * layouts on iOS Safari. Use dvh where the container relies on vh. */
  .oemd-chat.oemd-chat-hero {
    min-height: auto !important;
  }
}

/* 0149.L2 · HERO TILE GRID (Layer 2) ---------------------------------
 * Round 12 (2026-08-19): the 2-column override that used to live here
 * has been REMOVED. It fired from 414px up, which on a real iPhone Pro
 * Max produced 175-218px columns — narrow enough that "Troubleshoot a
 * system" wrapped to three lines and the "Start ->" pill printed on top
 * of the title. oem-dashboard.css:356 already states the tile minimum
 * as 260px; this rule ignored it and hard-coded two columns regardless
 * of whether two would fit.
 *
 * Column count is now derived from that 260px minimum in the L1 rule
 * above, so the hero goes 2-up only once two columns genuinely fit
 * (~560px and wider) and stays 1-up on every phone below that. The
 * line-clamp below is kept: it still applies whenever 2-up is reached. */
/* Superseded by the tile sizing system in oem-dashboard.css. This block
   used to set clamp:3 !important here while another block set clamp:2
   elsewhere, and the two fought by source order. There is one knob now,
   --tile-sub-lines, and this breakpoint no longer needs its own opinion. */

/* 0149.L3 · CHAT BUBBLE MAX WIDTH (Layer 2) --------------------------
 * Spec 0132 already caps .eng-msg at 96% under 767.98. Tighten to
 * 85vw at <=414 per spec so long bubbles do not blow through the safe
 * area padding on iPhone SE / mini. */
@media (max-width: 414px) {
  .eng-msg {
    max-width: 85vw !important;
  }
}

/* 0149.L4 · KANBAN HORIZONTAL SCROLL (Layer 3) -----------------------
 * focus-apps.css already stacks .app-kanban-board to 1fr at <=900px.
 * BUILDER decision (documented in READY report): keep vertical stack
 * (baseline) because horizontal scroll on a 3-column board hides two
 * lanes at once and requires tap-scroll gymnastics on <=414 devices.
 * Vertical stack shows every card in reading order and the To Do /
 * In Progress / Done column heads act as section headers. What we DO
 * add: bring the 1fr breakpoint down to 640px (tablet portrait 768
 * keeps 3-up which reads fine) and tighten column padding + gap. */
@media (max-width: 640px) {
  .app-kanban-board {
    grid-template-columns: 1fr !important;
    gap: 10px !important;
  }
  .app-kanban-col {
    padding: 10px !important;
    min-height: 0 !important;
  }
  .app-kanban-col-head {
    padding: 2px 4px 6px !important;
    position: sticky !important;
    top: 0 !important;
    background: rgba(15, 28, 48, .96) !important;
    z-index: 1 !important;
  }
}

/* 0149.L5 · FILTER PILL ROW WRAP + HORIZONTAL SCROLL (Layers 3-6) ----
 * .app-cat-pills currently flex-wraps which stacks pills to two rows
 * at 375. That is acceptable per spec (wraps to 2 lines). What we fix:
 *   - the trailing .app-search block inside .app-cat-pills currently
 *     uses margin-left:auto + min-width:200px which forces overflow
 *     at 375. Drop it to full-width on its own row.
 *   - the .app-type-pills leading label needs to sit above its pills
 *     at 375, not inline. */
@media (max-width: 640px) {
  .app-cat-pills {
    gap: 6px !important;
    row-gap: 8px !important;
  }
  .app-cat-pills .app-search {
    margin-left: 0 !important;
    min-width: 0 !important;
    width: 100% !important;
    flex: 1 1 100% !important;
    order: 99 !important;
  }
  .app-type-pills {
    margin-top: 0 !important;
  }
  .app-type-pills-label {
    width: 100% !important;
    padding-right: 0 !important;
    padding-bottom: 2px !important;
  }
  .app-cat-pill {
    padding: 8px 14px !important;
    font-size: 12px !important;
    min-height: 36px !important;
  }
}

/* 0149.L6 · CARD PADDING TIGHTEN (Layer 3) --------------------------- */
@media (max-width: 640px) {
  .app-card-body {
    padding: 12px !important;
    gap: 6px !important;
  }
  .app-card {
    min-height: 0 !important;
  }
  /* Recommended rail cards fit two-thirds of the viewport so the next
   * card peeks in and users know the row is scrollable. */
  .app-recommended-rail {
    margin: 0 0 20px !important;
  }
  .app-recommended-rail-scroll {
    grid-auto-columns: minmax(240px, 78vw) !important;
    scroll-snap-type: x mandatory !important;
  }
  .app-recommended-rail-scroll .app-card {
    scroll-snap-align: start !important;
  }
}

/* 0149.L7 · WAITLIST INPUT / BUTTON STACK (Layer 4) ------------------
 * ymh-waitlist-form.js paints inline styles: flex:1 1 220px on the
 * input and flex:0 0 auto on the button, inside a flex-wrap:wrap form.
 * At 375 the input min 220 + button ~130 overflows. Force each row to
 * 100% flex-basis so the button drops below and both are full-width. */
@media (max-width: 640px) {
  .ymh-waitlist[data-role="ymh-waitlist-form"] {
    max-width: 100% !important;
  }
  .ymh-waitlist [data-role="ymh-waitlist-email"] {
    flex: 1 1 100% !important;
    min-width: 0 !important;
    width: 100% !important;
    min-height: 44px !important;
  }
  .ymh-waitlist [data-role="ymh-waitlist-submit"] {
    flex: 1 1 100% !important;
    width: 100% !important;
    min-height: 44px !important;
  }
}

/* 0149.L8 · CALENDAR CELL + MONTHNAV (Layer 5) -----------------------
 * .cal-monthnav .btn is 32x32 in the inline style block; bump to 44x44
 * on touch. Also shrink the day cell auto-row so a full month fits
 * without a page-height jump, and constrain event chips to a single
 * line ellipsis so long titles do not blow the cell. */
@media (max-width: 640px) {
  .cal-grid {
    grid-auto-rows: 64px !important;
  }
  .cal-cell {
    padding: 4px 4px 2px !important;
  }
  .cal-day {
    font-size: 12px !important;
    margin-bottom: 2px !important;
  }
  .cal-event {
    font-size: 10px !important;
    padding: 2px 4px !important;
    white-space: nowrap !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
    max-width: 100% !important;
  }
  .cal-header .dow {
    font-size: 9px !important;
    padding: 6px 0 !important;
  }
  .cal-monthnav .btn {
    width: 44px !important;
    height: 44px !important;
    min-width: 44px !important;
  }
  .cal-monthnav {
    gap: 6px !important;
  }
  .cal-monthnav .month {
    font-size: 14px !important;
  }
  .cal-scale button {
    min-height: 40px !important;
    padding: 6px 10px !important;
  }
  .cal-legend {
    gap: 10px !important;
  }
  .cal-legend .item {
    font-size: 11px !important;
  }
  /* Navy topbar row on calendar page: the two .app-nb-right blocks
   * plus tabs push the ＋ New project button off-screen. Wrap them
   * onto their own row and let them fill width. */
  .app-navy-topbar {
    flex-wrap: wrap !important;
    gap: 8px !important;
  }
  .app-navy-topbar .app-nb-right {
    flex: 1 1 100% !important;
    justify-content: flex-start !important;
    flex-wrap: wrap !important;
  }

  /* 0150-hotfix (owner iPhone Plus 428 screenshot 2026-08-14): the
   * .app-navy container had margin: 0 32px 32px + padding: 20px which
   * pushed the dark card past the right viewport edge on /app/settings,
   * /app/documents, /app/equipment. Tighten both on mobile so the card
   * fits inside the phone viewport. */
  .app-navy {
    margin: 0 12px 20px !important;
    padding: 14px !important;
    box-sizing: border-box !important;
    max-width: calc(100vw - 24px) !important;
    overflow-x: hidden !important;
  }

  /* App chat message bubbles: paid captain chat surface uses .eng-msg
   * too but the user bubble was clipping on the right on iPhone Plus.
   * Same treatment as spec 0150 Layer 5 for /engineer public chat. */
  .eng-msg,
  .eng-msg.user,
  .eng-msg.bot {
    max-width: min(85vw, 100%) !important;
    overflow-wrap: anywhere !important;
    word-break: break-word !important;
    box-sizing: border-box !important;
  }

  /* Topbar title "Yacht Assistant" / "Yachtmasters Hub" was wrapping to
   * 2 lines on 428, making the entire topbar taller than needed. Shrink
   * font size on mobile so it fits on one line. */
  .appshell-tb-title {
    font-size: 13px !important;
    letter-spacing: 0 !important;
    white-space: nowrap !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
    max-width: 45vw !important;
  }
}

/* 0149.L9 · EQUIPMENT / DOCUMENTS LIST STACK (Layers 6-7) ------------
 * .app-eq-row uses grid 44px | 1fr | auto. The right column (Active
 * pill) collides with long titles at 375. Stack the right column below
 * the body so title has room. Search input full width. */
@media (max-width: 640px) {
  .app-eq-row {
    grid-template-columns: 44px 1fr !important;
    grid-template-areas:
      "icon body"
      "right right" !important;
    padding: 12px 14px !important;
    gap: 10px !important;
  }
  .app-eq-row .app-eq-icon { grid-area: icon !important; }
  .app-eq-row .app-eq-body { grid-area: body !important; }
  .app-eq-row .app-eq-right {
    grid-area: right !important;
    flex-direction: row !important;
    align-items: center !important;
    justify-content: flex-start !important;
  }
  .app-eq-cat { font-size: 10px !important; }
  .app-eq-title { font-size: 14px !important; }
  .app-eq-sub { font-size: 12px !important; }
  .app-search {
    margin-left: 0 !important;
    width: 100% !important;
    min-width: 0 !important;
  }
  .app-search input {
    font-size: 14px !important;
    padding: 10px 14px !important;
    min-height: 40px !important;
  }
  .app-filters {
    gap: 6px !important;
  }
  .app-filter {
    min-height: 36px !important;
    font-size: 12px !important;
  }
  /* Documents grid was 3-up above 700 and 1-up below; force 1-up at
   * <=640 too so long titles wrap naturally rather than truncate. */
  .app-docs-grid {
    grid-template-columns: 1fr !important;
  }
  .app-doc-title { font-size: 14px !important; }
  .app-doc-meta { font-size: 12px !important; }
  .app-doc-kind { font-size: 10px !important; }
}

/* 0149.L10 · SETTINGS FORM (Layer 8) ---------------------------------
 * .as-row uses grid 220px | 1fr which is comfortable at desktop but
 * squishes the input column at 375. Stack label above input on mobile
 * and let inputs use full width (was max-width 360). Buttons full
 * width in .as-actions so Save / Reset are easy to hit. */
@media (max-width: 640px) {
  .as-nav {
    overflow-x: auto !important;
    -webkit-overflow-scrolling: touch !important;
    scrollbar-width: none !important;
    flex-wrap: nowrap !important;
    padding-bottom: 4px !important;
  }
  .as-nav::-webkit-scrollbar { display: none !important; }
  .as-tab {
    flex: 0 0 auto !important;
    min-height: 40px !important;
    font-size: 13px !important;
  }
  .as-row {
    grid-template-columns: 1fr !important;
    gap: 8px !important;
    padding: 12px 0 !important;
  }
  .as-row .lbl { font-size: 12px !important; }
  .as-row .lbl-sub { font-size: 12px !important; }
  .as-row input[type="text"],
  .as-row input[type="email"] {
    max-width: 100% !important;
    font-size: 16px !important; /* iOS: prevents zoom on focus */
    padding: 11px 12px !important;
    min-height: 44px !important;
  }
  .as-card {
    padding: 14px !important;
  }
  .as-actions {
    flex-direction: column !important;
    gap: 8px !important;
  }
  .as-actions .as-btn {
    width: 100% !important;
    min-height: 44px !important;
    padding: 12px 18px !important;
    font-size: 14px !important;
  }
  .as-h { font-size: 15px !important; }
  .as-hp { font-size: 13px !important; }
}

/* 0149.L11 · NOTIFICATION BELL (Layer 9) -----------------------------
 * The bell mounts via ymh-notifications.js. Bump touch target and
 * clamp the panel so it never clips off the right edge at 375. The
 * spec 0132 rule already sets left:6px right:6px on .ymh-notif-panel;
 * add the trigger button target here. */
@media (max-width: 767.98px) {
  #ymh-notif-bell,
  .ymh-notif-bell,
  [data-role="ymh-notif-bell"] {
    min-width: 44px !important;
    min-height: 44px !important;
  }
  #ymh-notif-bell button,
  .ymh-notif-bell button {
    min-width: 44px !important;
    min-height: 44px !important;
  }
  /* Belt-and-suspenders position clamp in case the panel uses right:0
   * only. Overrides any inline "right: <negative>" from the widget. */
  .ymh-notif-panel {
    max-width: calc(100vw - 12px) !important;
  }
}

/* 0149.L12 · FONT-SIZE FLOOR (Layer 9) -------------------------------
 * Enforce 14px body / 12px chip minimum on mobile. Overrides any
 * inline or component styles that dip below. Anchor to .appshell so
 * marketing pages are untouched. */
@media (max-width: 640px) {
  .appshell .app-hero-sub,
  .appshell .app-crumb,
  .appshell .oemd-tile-sub,
  .appshell .app-card-title,
  .appshell .app-card-next,
  .appshell .app-eq-sub,
  .appshell .app-doc-meta {
    font-size: max(12px, 1em) !important;
  }
  .appshell .chip {
    font-size: 12px !important;
    padding: 4px 10px !important;
  }
  .appshell .app-card-next {
    font-size: 12px !important;
  }
  .appshell .app-card-foot {
    font-size: 12px !important;
  }
  .appshell .app-eq-cat,
  .appshell .app-doc-kind {
    font-size: 10px !important;
    letter-spacing: .08em !important;
  }
  /* Category chip inside cards uses .chip.cat modifiers; the floor
   * above covers them via .chip. */
}

/* ═══════════════════════════════════════════════════════════════════
 * Spec 0150 · Public surfaces mobile pass
 * ═══════════════════════════════════════════════════════════════════
 * Owner iPhone screenshots 2026-08-14 flagged public surfaces
 * (/engineer via /try, /pricing, /, /login) as broken at 375. Spec
 * 0149 covered /app/*; this covers the trial surfaces.
 *
 * DO NOT duplicate /app/* rules above. Each block below scopes to a
 * surface not covered by 0132/0149. Where a rule overlaps (rail
 * collapse, chat bubble), the 0132/0149 rule already covers /engineer
 * because it shares class names with /app; adjustments live in
 * engineer.css spec 0150 additions instead.
 *
 * Layers:
 *   0150.L1  Global mobile horizontal-scroll guard for public surfaces
 *   0150.L2  Landing (/) mobile polish (hero fits 375, plan grid, CTAs)
 *   0150.L3  Pricing (/pricing) mobile polish (nav wrap, waitlist stack)
 *   0150.L4  Login (/login) mobile polish (form full-width, tap 44px)
 * ═══════════════════════════════════════════════════════════════════ */

/* 0150.L1 · Horizontal-scroll guard for marketing pages -------------
 * The /app/* rule at spec 0132 L10 scopes to .appshell descendants.
 * Marketing pages (index, pricing, login) do not use .appshell so add
 * a body-level guard for those surfaces. Anchored via body:not(.oemd-page)
 * because /engineer sets body.oemd-page and already inherits the L10
 * guard through .appshell. */
@media (max-width: 767.98px) {
  body:not(.oemd-page):not(.oemd-shell) {
    overflow-x: hidden;
  }
}

/* 0150.L2 · Landing (/) mobile polish -------------------------------
 * Site.css already handles some polish at <=560 and <=380, but the
 * 561-767 band was thin. Add hero + plan grid rules there. */
@media (max-width: 767.98px) {
  /* Hero copy fits at 375 without horizontal overflow. */
  .hero .inner {
    padding-left: max(18px, env(safe-area-inset-left));
    padding-right: max(18px, env(safe-area-inset-right));
  }
  .hero h1 {
    font-size: clamp(28px, 7.4vw, 40px);
    line-height: 1.15;
  }
  .hero-sub {
    font-size: 15px;
    max-width: 100%;
  }
  .hero-ask {
    max-width: 100%;
  }
  .hero-ask-input {
    font-size: 16px; /* iOS zoom guard */
  }
  /* CTA buttons full-width at <=640 so the tap target spans the
   * comfortable phone thumb reach. */
  .hero-secondary {
    flex-direction: column;
    align-items: stretch;
  }
  .hero-onboard,
  .hero-demo {
    width: 100%;
    justify-content: center;
    min-height: 44px;
  }
  /* Nav toggle already 44x44; ensure the mobile menu items reach the
   * 44px tap target too. */
  .nav-links a {
    min-height: 44px;
    display: flex;
    align-items: center;
  }
}
@media (max-width: 640px) {
  /* Landing pricing preview stacks 1-col (site.css already sets this at
   * <=900 for .price-grid; add tighter padding at 375). */
  .price-grid {
    gap: 14px;
  }
  .pcard {
    padding: 22px 18px;
  }
}

/* 0150.L3 · Pricing (/pricing) mobile polish -------------------------
 * pricing-hero + pricing-faq are the pricing-specific surfaces. Waitlist
 * input/button live inside a .ymh-waitlist form (rendered by
 * ymh-waitlist-form.js) already covered by spec 0149.L7 but only when
 * the appshell wraps it. On /pricing the form mounts inline so add
 * an unscoped stack rule. */
@media (max-width: 640px) {
  .pricing-hero {
    padding-left: 18px;
    padding-right: 18px;
    padding-top: calc(var(--nav-h, 78px) + 40px);
    padding-bottom: 50px;
  }
  .pricing-hero h1 {
    font-size: clamp(28px, 8vw, 40px);
  }
  .pricing-hero p {
    font-size: 15px;
  }
  .pricing-faq {
    margin: 32px 0 0;
    padding: 0 4px;
  }
  .pricing-faq details {
    padding: 14px 16px;
  }
  .pricing-faq summary {
    font-size: 15px;
  }
  /* Nav login pill in the topbar can crowd the burger at 375. Let it
   * shrink and wrap into the drawer via .nav-links stacking. */
  #navLogin {
    margin-left: 0 !important;
    padding: 10px 14px !important;
    min-height: 44px !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
  }
}

/* 0150.L4 · Login (/login) mobile polish -----------------------------
 * The /login inline styles already set .lg-wrap max-width 400 with
 * 40px 20px padding. At 375 the padding + input padding work but the
 * submit button is not full-width tap-friendly on some iOS variants.
 * Enforce 44px min tap and safe-area padding. */
@media (max-width: 640px) {
  body.oemd-page:has(.lg-wrap) {
    padding-top: 0 !important;
    padding-left: max(0px, env(safe-area-inset-left));
    padding-right: max(0px, env(safe-area-inset-right));
    padding-bottom: env(safe-area-inset-bottom);
  }
  .lg-wrap {
    padding: 28px 18px calc(28px + env(safe-area-inset-bottom)) !important;
    max-width: 100% !important;
  }
  .lg-field input {
    min-height: 44px;
    font-size: 16px !important; /* iOS zoom guard */
  }
  .lg-btn {
    min-height: 48px;
    font-size: 15px;
  }
  .lg-h {
    font-size: 24px;
  }
  .lg-p {
    font-size: 13.5px;
    margin-bottom: 24px;
  }
  .lg-brand {
    margin-bottom: 28px;
  }
  /* Google OAuth mount uses the shared .ymh-signin-button pattern. Give
   * it full-width parity with the form fields. */
  .lg-oauth [data-ymh-signin] > * {
    width: 100%;
    box-sizing: border-box;
  }
  .lg-oauth .ymh-signin-button,
  .lg-oauth button {
    width: 100%;
    min-height: 44px;
  }
}

/* ═══════════════════════════════════════════════════════════════════
 * PRODUCT DECISION, flagged for review · round 12 (2026-08-19)
 * ═══════════════════════════════════════════════════════════════════
 * The topbar cluster needs ~391px of content in a ~363px slot (375) or
 * ~308px slot (320). Truncation alone cannot close that: even with the
 * identity chip clamped, the numbers do not fit, and the squeeze pushes
 * .appshell-tb-left to zero width so the VESSEL NAME disappears.
 * Something has to leave the topbar.
 *
 * Scope was <=480px until the boundary sweep in
 * tests/e2e/33-responsive-regression.spec.ts measured the cluster at
 * 654px inside a 641px viewport on all seven surfaces, signed in — the
 * email in the identity chip is long enough that 481-767 is cramped
 * too. Widened to the full mobile range rather than chasing another
 * arbitrary cutoff.
 *
 * Chosen: the "Get the app" pill (106.9px measured, the largest item
 * after the identity chip). It is a marketing CTA, not a task control;
 * every other item in the cluster is functional (notification bell,
 * plan state, sign out), and the vessel name is the one thing that
 * tells a captain which boat they are looking at.
 *
 * This is a judgement call, not a mechanical fix. Delete this block to
 * reverse it: the layout stays correct and the cluster clips on the
 * right again instead.
 *
 * Deliberately placed at END OF FILE. An earlier revision opened this
 * block in the middle of the L1 <=767.98px block, and because it reused
 * that block's closing brace it silently swallowed .appshell-main,
 * .appshell-rail and every rule after them, re-scoping them from 768px
 * down to 480px and breaking the whole 481-767px band. Keep new media
 * blocks at the end of the file, never spliced into an existing one.
 * ═══════════════════════════════════════════════════════════════════ */
@media (max-width: 767.98px) {
  .appshell-tb-cta {
    display: none !important;
  }
}

/* ═══════════════════════════════════════════════════════════════════
 * M-03 · 16px form controls · round 12 (2026-08-19)
 * ═══════════════════════════════════════════════════════════════════
 * Mobile Safari force-zooms the viewport whenever a focused input,
 * select or textarea computes below 16px, and it does NOT zoom back
 * out on blur. The captain taps a search box and the whole layout is
 * left wider than the screen until they pinch it back themselves.
 *
 * Audit round 12 measured every control in the app below the line:
 *   #aeqSearch 14px (12px at >=768)   #adocSearch 14px / 12px
 *   projects .app-search input 14/12  #asName/#asEmail/#asPhone 13px
 *   .ymh-eq-modal    8 fields @ 13px  .ymh-proj-modal  10 fields @ 13px
 *   .ymh-upload-modal 3 fields @ 13px
 *   .oemd-chat-hero .eng-input 14px below 640 (M-11)
 *
 * Scoped to controls only. Spec 0149.L12 sets a deliberate 14px floor
 * for STATIC TEXT and that stays: a 13px <button> label is fine, a
 * 13px <input> is not, because only the latter triggers the zoom.
 * ═══════════════════════════════════════════════════════════════════ */
@media (max-width: 1024px) {
  .appshell input,
  .appshell select,
  .appshell textarea,
  .oemd-chat input,
  .oemd-chat textarea,
  .eng-input,
  .oemd-chat-hero .eng-input,
  .ymh-eq-modal input,      .ymh-eq-modal select,      .ymh-eq-modal textarea,
  .ymh-proj-modal input,    .ymh-proj-modal select,    .ymh-proj-modal textarea,
  .ymh-projdetail-modal input, .ymh-projdetail-modal select, .ymh-projdetail-modal textarea,
  .ymh-upload-modal input,  .ymh-upload-modal select,  .ymh-upload-modal textarea,
  .ymh-task-modal input,    .ymh-task-modal select,    .ymh-task-modal textarea,
  .ymh-doc-modal input,     .ymh-doc-modal select,     .ymh-doc-modal textarea,
  .ymh-onb-card input,      .ymh-onb-card select,      .ymh-onb-card textarea {
    font-size: 16px !important;
  }
}

/* ═══════════════════════════════════════════════════════════════════
 * ROUND 12 · remaining audit items · M-05, M-06, M-07, M-08, M-09, M-10
 * ═══════════════════════════════════════════════════════════════════
 * Findings and measurements: testing-archive/mobile-audit-2026-08-19.md
 * ═══════════════════════════════════════════════════════════════════ */

/* M-08 · TYPE SCALE ---------------------------------------------------
 * The app rendered 18-19 distinct font-size/line-height pairs per page
 * at 375px and twelve distinct steps below 16px: 9, 9.5, 10.5, 11, 11.5,
 * 12, 12.5, 13, 13.33, 13.5, 14, 15. Three of those (13, 13.33, 13.5)
 * appear on the SAME page, which is not a scale, it is drift. Most text
 * also carried line-height: normal rather than a token.
 *
 * Five steps, each with a paired line-height. Deliberately conservative:
 * this collapses the sub-16px cluster onto real steps rather than
 * restyling the app. Spec 0114 established the CSS-token precedent.
 *
 * NOTE the interaction with 0149.L12, which sets a 14px floor for static
 * text on mobile. That floor stands and --ymh-fs-xs (12px) is used only
 * for chips and metadata above 640px, never for body copy on a phone. */
:root {
  --ymh-fs-xs: 12px;   --ymh-lh-xs: 16px;   /* chips, counts, metadata */
  --ymh-fs-sm: 14px;   --ymh-lh-sm: 20px;   /* secondary copy, labels   */
  --ymh-fs-md: 16px;   --ymh-lh-md: 24px;   /* body, form controls      */
  --ymh-fs-lg: 20px;   --ymh-lh-lg: 28px;   /* section headings         */
  --ymh-fs-xl: 32px;   --ymh-lh-xl: 40px;   /* page titles              */
}

@media (max-width: 767.98px) {
  /* Everything measured below 12px goes to the bottom step. These are
   * the ones 0149.L12's floor never covered: it names eight classes and
   * these were not among them. */
  .appshell .appshell-sect-label,   /* was 9.5px */
  .appshell .appshell-upgrade-tag,  /* was 9px   */
  .appshell .app-kanban-empty-sub,  /* was 10.5px */
  .appshell .rail-section-title,    /* was 11px  */
  .appshell .rail-vessel-meta,      /* was 11px  */
  .appshell .appshell-logo-sub {    /* was 11px  */
    font-size: var(--ymh-fs-xs) !important;
    line-height: var(--ymh-lh-xs) !important;
  }
  /* The 13 / 13.33 / 13.5 cluster collapses onto one step. */
  .appshell .oemd-tile-title,
  .appshell .oemd-tile-sub,
  .appshell .appshell-logo-title,
  .appshell .appshell-tb-title,
  .appshell .app-cards-label {
    font-size: var(--ymh-fs-sm) !important;
    line-height: var(--ymh-lh-sm) !important;
  }
}

/* M-05 · TOUCH TARGETS ------------------------------------------------
 * Between 2 and 33 interactive elements per surface measured under the
 * 44x44 iOS minimum, and the worst offenders are the shell's OWN
 * controls rather than page content: .appshell-identity-reset is
 * 23.2x30 on all seven surfaces at all four viewports.
 *
 * Height is added with min-height plus inline-flex centring so the text
 * baseline does not move. The two 15px-tall inline links get a hit area
 * via ::after instead, which grows the tappable box without changing a
 * single pixel of layout. */
@media (max-width: 1024px) {
  /* Two groups, and the distinction matters. The sidebar rows are
   * block-level and fill the drawer's 272px; forcing inline-flex on
   * them would collapse each one to its text width and wreck the nav.
   * They get block-level `flex`. The pills and tabs are inline by
   * nature and get `inline-flex`. */
  .appshell .appshell-nav-item,
  .appshell .appshell-hist-item,
  .appshell .appshell-newchat,
  .appshell .appshell-logout,
  .appshell .appshell-vessel-switch,
  .appshell .rail-qa-row,
  .appshell .app-rail-profile-cta {
    min-height: 44px !important;
    display: flex !important;
    align-items: center !important;
  }
  .appshell .app-tab,
  .appshell .app-btn,
  .appshell .app-cat-pill,
  .appshell .app-filter,
  .appshell .as-tab {
    min-height: 44px !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
  }
  /* Square controls: the composer trio and the shell's reset button. */
  #engMic, #engSend, #engAttach,
  .appshell .appshell-identity-reset,
  .appshell .appshell-burger {
    min-width: 44px !important;
    min-height: 44px !important;
  }
  /* Inline links too short to tap. ::after expands the hit box only —
   * position:relative on the anchor, no layout shift, no visual change. */
  .appshell .appshell-upgrade-link,
  .appshell .appshell-tb-back,
  .appshell .aeq-foot .link,
  .appshell .adoc-foot .link {
    position: relative !important;
  }
  .appshell .appshell-upgrade-link::after,
  .appshell .appshell-tb-back::after,
  .appshell .aeq-foot .link::after,
  .appshell .adoc-foot .link::after {
    content: "" !important;
    position: absolute !important;
    inset: -15px -8px !important;
  }
}

/* M-06 / M-07 · FIXED CHROME + GUIDE BUBBLE ---------------------------
 * On /try and /app at 320x568 the stacked chrome came to 182px, 32.0%
 * of the viewport: topbar 56 (9.9%) + composer 60 (10.6%) + guide bubble
 * 66 (11.6%). The bubble is the part that actually hurt — it is
 * position:fixed at 95% of viewport width and sat on top of the card
 * list, hiding the "Photo of what's broken" tile title outright, and its
 * dismiss control was inside the 44px minimum.
 *
 * Narrow it, lift it clear of the composer, and give the dismiss a real
 * hit area. The bubble stays; it is doing a job on first visit. */
@media (max-width: 767.98px) {
  .eng-guide-bubble {
    max-width: calc(100vw - 32px) !important;
    left: 16px !important;
    right: 16px !important;
    width: auto !important;
    bottom: calc(84px + env(safe-area-inset-bottom)) !important;
  }
  .eng-guide-bubble button,
  .eng-guide-bubble .eng-guide-close,
  .eng-guide-bubble [aria-label*="ismiss"],
  .eng-guide-bubble [aria-label*="lose"] {
    min-width: 44px !important;
    min-height: 44px !important;
  }
}

/* M-09 · DRAWER WIDTH -------------------------------------------------
 * The drawer measured 88.0% of a 320px viewport and 85.3% of 375px,
 * leaving 38px of page edge at 320 — under a thumb's width, so
 * tap-to-dismiss on the visible remainder is unreliable. The scrim
 * works, but the edge should be tappable too. */
@media (max-width: 767.98px) {
  .appshell-sidebar {
    max-width: min(320px, 84vw) !important;
  }
}

/* M-10 · SCROLL-LOCK OVERSHOOT ----------------------------------------
 * With the drawer open, body computed position:fixed at height 675px
 * against a 667px viewport — 101.2%, an 8px overshoot that shows as a
 * one-frame jump when the drawer closes. */
@media (max-width: 767.98px) {
  body.appshell-drawer-open,
  body.ymh-scroll-locked {
    height: 100% !important;
    max-height: 100% !important;
  }
}


/* ═══════════════════════════════════════════════════════════════════
 * ROUND 13 · TILE SIZING ON PHONES
 * ═══════════════════════════════════════════════════════════════════
 * The height system lives in oem-dashboard.css (.oemd-tiles). All this
 * block does is turn the knob for small screens and set the type. It
 * deliberately declares no clamp of its own: one source of truth. */
@media (max-width: 767.98px) {
  .appshell .oemd-tiles { --tile-sub-lines: 2; }
}
/* Below 480 the six tiles are stacked one-up, so their combined height is
   the whole first screen. Levelling everything to the tallest is the right
   call for consistency but the wrong one for a phone unless the tallest is
   also short, so the hint drops to a single line here. Measured at 393:
   two lines gives 6 x 114 = 684px of an 852px viewport, one line gives
   6 x 97 = 582px. The title is the label; the hint is a hint. */
@media (max-width: 479.98px) {
  .appshell .oemd-tiles { --tile-sub-lines: 1; }
  .appshell .oemd-tile-inner { padding: 8px 11px !important; }
  .appshell .oemd-tile-title { line-height: 1.3 !important; }
  .appshell .oemd-tile-sub {
    font-size: 12.5px !important;
    line-height: 1.4 !important;
  }
  .appshell .oemd-tile-cta {
    min-height: 36px !important;
    padding: 7px 12px !important;
  }
}
