/* ═══════════════════════════════════════════════════════════════════════
   mobile.css — shared responsive layer (Aug 2026)
   Loaded LAST on every page (after theme.css, console-chrome.css and the
   page's own inline <style>), so equal-specificity rules here win without
   needing !important. Where a runtime-injected <style> (nav.js) or a page
   rule is more specific, the selector is prefixed `html body`.

   Breakpoints — 900px: tablet / small laptop (sidebar drops, drawer takes over)
                 640px: phone landscape → portrait
                 400px: small phones (iPhone SE / mini)
   Nothing here applies above 900px: desktop rendering is untouched.
   ═══════════════════════════════════════════════════════════════════════ */

:root { --mo-hdr-h: 56px; }

/* ── Never let the page scroll sideways because of one stray element ───── */
@media (max-width: 900px) {
  html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
  html body { overflow-x: hidden; }
  html body img, html body video, html body canvas { max-width: 100%; }

  /* Flex/grid children default to min-width:auto, which is the single most
     common cause of "my flex row is wider than the phone": the item refuses to
     shrink below its widest child (a 1300px hall, a 12-column table…). */
  html body .header > *, html body .hdr > *,
  html body .content > *, html body .main > *,
  html body .page-wrap > *, html body .main, html body .content,
  html body .ff, html body .chart-panel, html body .panel, html body .card { min-width: 0; }
}

/* ═══ 1. Console header (app/stats/gantt/… `.header`, floor pages `.hdr`) ══
   Desktop packs the line selector, period buttons, clock and theme toggle in
   one row. On a phone that row is ~900px wide. Let it wrap into stacked rows
   and give every control a real touch target. */
@media (max-width: 900px) {
  html body .header, html body .hdr {
    flex-wrap: wrap; row-gap: 8px; column-gap: 10px;
    padding: 9px 12px; padding-right: 56px;   /* room for the burger */
    align-items: center;
    /* Several pages pin the bar to a one-row height (`height:50px`). Once it
       wraps, that box no longer contains its own rows and the second row paints
       over the page. */
    height: auto; min-height: 50px;
  }
  html body .header-left, html body .hdr-left,
  html body .header-right, html body .hdr-right {
    flex-wrap: wrap; row-gap: 8px; column-gap: 8px;
    min-width: 0; max-width: 100%;
  }
  /* the left block owns the row, the controls flow underneath it */
  html body .header-left, html body .hdr-left { flex: 1 1 100%; }
  html body .header-right, html body .hdr-right { flex: 1 1 100%; margin-left: 0; }

  /* Button rows (line selector, period selector, shift selector) */
  html body .line-btn, html body .period-btn, html body .shift-btn,
  html body .export-btn, html body .theme-toggle {
    min-height: 34px;
  }
  /* Inner wrappers (a <span> or <div> holding the line-selector buttons) are
     flex rows too — they must wrap as well, or they overflow on their own. */
  html body .header > *, html body .hdr > *,
  html body .header-left > *, html body .header-right > *,
  html body .hdr-left > *, html body .hdr-right > * {
    flex-wrap: wrap; min-width: 0; max-width: 100%;
  }
  /* Clock / secondary meta: keep it, but it must never force a new row alone */
  html body .header-right > span, html body .hdr-right > span { font-size: 12px; }
}

@media (max-width: 640px) {
  /* Smaller chips fit more per row — the console header costs 2 rows, not 4 */
  html body .line-btn, html body .period-btn, html body .shift-btn,
  html body .export-btn { padding: 6px 11px; font-size: 12px; }
  html body .header, html body .hdr { row-gap: 6px; column-gap: 8px; }
  html body .header h1, html body .hdr h1 { font-size: 15px; }
  html body .header h1 span, html body .hdr h1 span { display: none; }
  /* Truncate a long brand/context instead of pushing the row wider */
  html body .hdr-wordmark, html body .header h1, html body .hdr h1 {
    min-width: 0; overflow: hidden; text-overflow: ellipsis;
  }
}

/* ── Vitrine header (index/about/case-study/… `.nav-inner`) ─────────────── */
@media (max-width: 640px) {
  html body .nav-inner { gap: 10px; min-width: 0; }
  html body .nav-inner .brand { min-width: 0; overflow: hidden; }
  html body .nav-inner .brand span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  html body .nav-right { gap: 6px; flex-shrink: 0; }
}
@media (max-width: 400px) {
  html body .nav-inner .brand span { display: none; }   /* mark only */
}

/* ═══ 2. Mobile drawer (injected by mobile.js) ═════════════════════════════
   Replaces the old bottom tab scroller: the full grouped navigation, one
   thumb-reachable sheet, instead of ~20 icons in a 60px strip. */
.mo-burger {
  position: fixed; top: 8px; right: 10px; z-index: 120;
  width: 40px; height: 40px; border-radius: 11px;
  display: none; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--card, #23272e) 88%, transparent);
  border: 1px solid var(--border, #333842); color: var(--text, #e4e6eb);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  cursor: pointer; transition: .15s;
}
.mo-burger svg { width: 20px; height: 20px; display: block; }
.mo-burger:active { transform: scale(.94); }
.mo-burger:focus-visible { outline: 2px solid var(--accent, #4facfe); outline-offset: 2px; }

.mo-scrim {
  position: fixed; inset: 0; z-index: 990; display: none;
  background: rgba(0, 0, 0, .55);
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
  opacity: 0; transition: opacity .22s;
}
.mo-scrim.on { display: block; opacity: 1; }

.mo-drawer {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 991;
  width: min(88vw, 330px);
  background: var(--card, #16181d);
  border-left: 1px solid var(--border, #333842);
  box-shadow: -18px 0 50px -20px rgba(0, 0, 0, .8);
  transform: translateX(102%); transition: transform .26s cubic-bezier(.2,.7,.2,1);
  display: flex; flex-direction: column;
  padding-bottom: env(safe-area-inset-bottom, 0px);
  overscroll-behavior: contain;
}
.mo-drawer.on { transform: none; }
.mo-drawer-hd {
  display: flex; align-items: center; gap: 10px; flex-shrink: 0;
  padding: 14px 14px 12px; border-bottom: 1px solid var(--border, #333842);
  padding-top: max(14px, env(safe-area-inset-top, 0px));
}
.mo-drawer-hd .t {
  font-size: 13px; font-weight: 800; letter-spacing: .04em;
  text-transform: uppercase; color: var(--text-dim, #8b8f96);
}
.mo-drawer-hd .x {
  margin-left: auto; width: 34px; height: 34px; border-radius: 9px;
  display: grid; place-items: center; cursor: pointer;
  background: none; border: 1px solid var(--border, #333842); color: var(--text, #e4e6eb);
}
.mo-drawer-hd .x svg { width: 17px; height: 17px; }
.mo-drawer-bd { flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch; padding: 6px 0 22px; }

/* the drawer hosts the sidebar markup verbatim — retune it for touch */
.mo-drawer-bd .nav-item { padding: 12px 18px; font-size: 14px; min-height: 44px; }
.mo-drawer-bd .nav-sec  { padding: 14px 18px 5px; }
.mo-drawer-bd .nav-group-hd { padding: 13px 18px 9px; min-height: 42px; }
.mo-drawer-bd .sb-brand { padding: 2px 16px 13px; }
.mo-drawer-bd .sb-site  { margin: 8px 14px 12px; padding: 11px 13px; }

@media (max-width: 900px) {
  .mo-burger { display: flex; }
  /* the old bottom tab bar is superseded by the drawer */
  html body .mobile-nav { display: none !important; }
}

/* ═══ 3. Shopfloor halls — pan instead of shrink ═══════════════════════════
   `.ff` wraps a 1300×620 top-down SVG. Fitted to 390px it is 6px-tall text:
   unreadable. Below 860px the hall becomes a horizontal pan surface at a
   legible minimum width, with a one-time affordance. */
@media (max-width: 860px) {
  html body .ff {
    overflow-x: auto; overflow-y: hidden;
    -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain;
    scrollbar-width: thin;
  }
  html body .ff > svg { min-width: 880px; }
  html body .ff::-webkit-scrollbar { height: 5px; }
  html body .ff::-webkit-scrollbar-thumb { background: var(--border, #333842); border-radius: 3px; }
  .mo-panhint {
    position: absolute; top: 10px; left: 50%; transform: translateX(-50%);
    z-index: 5; pointer-events: none;
    display: flex; align-items: center; gap: 7px;
    padding: 6px 13px; border-radius: 18px;
    background: color-mix(in srgb, var(--card, #23272e) 92%, transparent);
    border: 1px solid var(--border, #333842);
    font-size: 11px; font-weight: 700; letter-spacing: .04em;
    text-transform: uppercase; color: var(--text-dim, #8b8f96);
    -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
    animation: moHint 4.5s ease forwards;
  }
  .mo-panhint svg { width: 14px; height: 14px; }
  @keyframes moHint { 0%,72% { opacity: 1 } 100% { opacity: 0 } }
}

/* ═══ 4. Wide tables — scroll the table, not the page ══════════════════════ */
.mo-scroll {
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain; max-width: 100%;
}
.mo-scroll > table { min-width: max-content; }
.mo-scroll::-webkit-scrollbar { height: 5px; }
.mo-scroll::-webkit-scrollbar-thumb { background: var(--border, #333842); border-radius: 3px; }

/* ═══ 5. Content density ═══════════════════════════════════════════════════ */
@media (max-width: 900px) {
  html body .content { padding: 12px; gap: 12px; }
  html body .sidebar { display: none; }

  /* Multi-column layouts that are unreadable on a phone */
  html body .bottom, html body .grid-2, html body .grid-3,
  html body .two-col, html body .split, html body .btm,
  html body .cols, html body .col2, html body .row2 { grid-template-columns: 1fr; }

  /* Chip / pill rows: wrap rather than overflow */
  html body .filter-bar, html body .ch-pills, html body .andon,
  html body .crew-strip, html body .legend, html body .agv-pills,
  html body .hero, html body .hero-row,
  /* card headers: a title on the left, a live meta group pushed right by
     `margin-left:auto` — on a phone the group lands outside the card */
  html body .fc-hdr, html body .cure, html body .sec-h,
  html body .panel-hdr, html body .card-hdr { flex-wrap: wrap; }
  html body .fc-hdr > *, html body .cure > * { min-width: 0; }

  /* Cards with `overflow:hidden` silently swallow whatever does not fit — a
     truncated live sentence reads as a shorter sentence, not as missing data. */
  html body .hs-sub {
    white-space: normal; overflow: visible; text-overflow: clip;
  }

  /* Charts keep a usable aspect on a narrow screen */
  html body .chart-panel canvas, html body .chart-box canvas { max-height: 44vh; }
}

@media (max-width: 640px) {
  html body .content { padding: 10px; }
  html body .ch-hero { padding: 14px 15px 13px; }
  html body .ch-title { font-size: 19px; }
  html body .ch-sub { font-size: 11px; }
  html body .kpi-value, html body .kpi .v { font-size: 20px; }
  /* KPI bands: two per row is the readable floor */
  html body .kpi-bar, html body .kpi-strip, html body .kstrip {
    grid-auto-flow: row; grid-auto-columns: unset;
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@media (max-width: 900px) {
  /* Chips carry live sentences ("Lineside rotors @A020 low (0 pcs · 0 pal)").
     A single-line pill is wider than the column it sits in — let them wrap. */
  html body .fcast-chip, html body .andon-chip, html body .ch-pill,
  html body .chip, html body .crew-chip, html body .spill,
  html body .pill, html body .mchip, html body .statepill, html body .kk-l {
    white-space: normal; max-width: 100%;
  }

  /* The floor-page hero docks a 3-up KPI strip beside the product shot; the
     `.hero .kstrip` rule outranks a single-class override, hence the pairing. */
  html body .hero .kstrip {
    grid-template-columns: repeat(2, minmax(0, 1fr)); width: 100%; margin-left: 0;
  }
  html body .hero .kk { min-width: 0; }
}
@media (max-width: 400px) {
  html body .kpi-bar, html body .kpi-strip, html body .kstrip { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  html body .ch-title { font-size: 17px; }
}

/* ═══ 6. Floating actions — clear of the thumb zone and of each other ═════ */
@media (max-width: 900px) {
  /* Both FABs used to clear the bottom tab bar (bottom:80px). The bar is gone,
     so they stack in the right-hand thumb column instead of sitting side by
     side across the middle of the screen. */
  html body .scan-fab, html body .chat-fab {
    width: 50px; height: 50px; right: 14px;
  }
  html body .scan-fab { bottom: max(14px, env(safe-area-inset-bottom, 0px)); }
  html body .chat-fab { bottom: calc(max(14px, env(safe-area-inset-bottom, 0px)) + 60px); }
  html body .chat-panel { width: 100vw; border-left: none; }
}

/* ═══ 7. Touch targets & focus ═════════════════════════════════════════════ */
@media (max-width: 900px) and (pointer: coarse) {
  html body a.nav-item, html body .mobile-nav a { min-height: 44px; }
  html body button, html body select, html body input[type="date"],
  html body input[type="text"], html body input[type="search"] { min-height: 34px; }
  html body select, html body input { font-size: 16px; }  /* stops iOS zoom-on-focus */
}

/* Long unbreakable strings (serials, URLs, JSON payloads) must not stretch the
   page — they wrap or their own box scrolls. */
@media (max-width: 900px) {
  html body pre, html body code, html body samp { overflow-x: auto; max-width: 100%; }
  html body .serial, html body .trace-id, html body .lot { overflow-wrap: anywhere; }
}

/* Modals / overlays must fit the small viewport */
@media (max-width: 640px) {
  html body .modal, html body .drawer-panel, html body .sheet {
    max-width: 100vw; max-height: 88vh; overflow-y: auto;
  }
}

/* ═══ 8. Tablet-width header ═══════════════════════════════════════════════
   The sidebar still belongs on a 1024px screen, but the header's control row
   (line selector + period selector + clock + toggles) does not fit there. Wrap
   it from 1100px down; everything else stays desktop until 900px. */
@media (max-width: 1100px) and (min-width: 901px) {
  html body .header, html body .hdr {
    flex-wrap: wrap; row-gap: 8px; height: auto; min-height: 50px;
  }
  html body .header > *, html body .hdr > *,
  html body .header-left, html body .header-right,
  html body .hdr-left, html body .hdr-right {
    flex-wrap: wrap; min-width: 0; max-width: 100%;
  }
}

/* The shift-forecast risk chips (`.fcast-chip`, the five *-floor pages) hold a
   live sentence, not a label — `white-space:nowrap` makes a single chip wider
   than its grid column on anything narrower than a desktop. */
@media (max-width: 1200px) {
  html body .fcast-chip { white-space: normal; max-width: 100%; }
}
