/* ng-mobile-revamp.css — the small-resolution revamp (2026-09-06).
 *
 * the operator's ask, verbatim: "it's so crowded that I can't even barely see the
 * chat. I just need to be able to easily navigate, chat, see previous chats,
 * use the meeting and voice buttons are the big priority on mobile or ipad."
 *
 * MEASURED BEFORE (headless Chrome, mockup-v11.html, 2026-09-06):
 *   iPhone 15 Pro 393x852 — stream 391px  =  46% of the screen
 *   iPhone SE    375x667 — stream 158px  =  24% of the screen  (composer 174px,
 *                                            i.e. the composer was BIGGER than
 *                                            the conversation)
 *   iPad         820x1180 — stream 262px tall and only 400px WIDE of 820, the
 *                           bottom nav gone entirely, telemetry eating 176px,
 *                           and the desktop REPLAY/DIFF + FIRST TOKEN hero back.
 *
 * ROOT CAUSES this file addresses:
 *   1. The phone rules stopped at 600px and `.bottomnav` was killed at 601px,
 *      so every tablet width got the DESKTOP layout squeezed — no mobile nav,
 *      no chat optimizations. The mobile range is now <=1024px, one breakpoint.
 *   2. #nvr-pane (VOICE REPLIES) held a 142px band that was empty most of the
 *      time, mid-screen, between the stream and the composer.
 *   3. The composer had grown to ELEVEN visible children (model chip, lane chip,
 *      VISION, SNIP, ATTACH, emoji, GIF, AUTO, PROMPTS, input, send) wrapping
 *      onto three rows. They collapse into one `+` sheet — see ng-mobile-revamp.js.
 *   4. #mtg-fab painted ON TOP of the voice-replies pane text (both floating,
 *      z 181 vs 58). Both floating pills are replaced by one docked action bar.
 *
 * SCOPE DISCIPLINE. Everything here is inside `@media (max-width:1200px)` and
 * most of it is further scoped to `body.ngm-on`, the class ng-mobile-revamp.js
 * sets. Desktop >=1025px renders byte-identical with this sheet loaded.
 * MERIDIAN design law is kept: one hero cyan, amber for signal only, no second
 * decorative hue introduced.
 */

@media (max-width: 1200px) {

  /* =====================================================================
   * 1. SHELL — the phone shell now covers tablets too.
   * mockup-v11.html:546 has `@media (min-width:601px){.bottomnav{display:none}}`
   * which is what stranded the iPad with no navigation at all.
   * ===================================================================== */
  .bottomnav {
    display: flex !important;
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 50;
    height: calc(64px + env(safe-area-inset-bottom));
    padding-bottom: env(safe-area-inset-bottom);
    padding-left: env(safe-area-inset-left); padding-right: env(safe-area-inset-right);
    align-items: center; justify-content: space-around;
    background: rgba(3, 8, 16, .88);
    backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
    border-top: 1px solid var(--line);
  }
  /* .bn-btn, its svg, .active and .bn-chat are ALL styled inside the <=600px
     block (mockup-v11.html:530-533). Showing .bottomnav at tablet widths without
     them left the icons unstyled — they rendered as full-size grey blocks
     overflowing the bar on the iPad. Restate them for the whole mobile range. */
  .bn-btn {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 3px; background: none; border: 0; color: var(--t2);
    font-size: 9px; font-weight: 600; letter-spacing: .12em;
    width: 56px; height: 48px;
  }
  .bn-btn svg { width: 20px; height: 20px; stroke: currentColor; stroke-width: 1.5; fill: none; }
  .bn-btn.active { color: var(--hue); }
  .bn-chat {
    background: color-mix(in srgb, var(--hue) 12%, rgba(6, 13, 26, .9));
    border: 1px solid color-mix(in srgb, var(--hue) 55%, transparent);
    border-radius: var(--r2); color: var(--hue);
    box-shadow: 0 0 16px color-mix(in srgb, var(--hue) 25%, transparent);
  }

  /* The full-bleed background layers (.aurora, .stars) and .statusbar are sized
     100vw, which INCLUDES the scrollbar gutter while clientWidth excludes it —
     measured 5px of horizontal scroll at 1180x820 with a classic scrollbar
     (innerWidth 1185 vs clientWidth 1180). iOS/iPadOS use overlay scrollbars so
     it rarely shows there, but nothing in this shell should ever scroll
     sideways, so pin it shut. */
  html, body { overflow-x: hidden; max-width: 100%; }

  .rail { display: none !important; }

  /* The telemetry column is fleet status, not conversation. On a phone it was
     already hidden; on a tablet it was a 176px band above the chat. It lives on
     HOME and in the TELEMETRY view, so nothing is lost. */
  .telemetry { display: none !important; }

  .app {
    grid-template-columns: minmax(0, 1fr) !important;
    grid-template-rows: minmax(0, 1fr) !important;
    padding-top: calc(var(--ngm-sb, 48px) + env(safe-area-inset-top));
    padding-bottom: calc(64px + env(safe-area-inset-bottom));
  }
  /* The 601-1023px block (mockup-v11.html:1927) pins `.center{grid-column:2;
     grid-row:2}` for its 60px-rail + telemetry-strip layout. With the rail and
     the strip gone and one track left, those placements put .center in an
     IMPLICIT second column — measured at left:820 in an 820px viewport, i.e.
     the entire chat rendered off the right edge of the iPad. Re-home every
     grid child explicitly rather than relying on auto-placement. */
  .center, .rail, .telemetry {
    grid-column: 1 !important;
    grid-row: 1 !important;
  }
  .center { overflow: visible; }
  .view.active {
    position: fixed;
    top: calc(var(--ngm-sb, 48px) + env(safe-area-inset-top));
    bottom: calc(64px + env(safe-area-inset-bottom));
    left: 0; right: 0;
  }

  /* Status bar: at 393px "ALL SYSTEMS NOMI…" was truncated and the AWAKE chip
     ran off the right edge with no affordance saying more existed. Keep it one
     scrollable row, and drop the pieces that repeat what the nav already says. */
  .statusbar {
    height: calc(48px + env(safe-area-inset-top));
    padding-top: env(safe-area-inset-top);
    gap: 8px;
    overflow-x: auto; overflow-y: hidden;
    scrollbar-width: none; -webkit-overflow-scrolling: touch;
  }
  .statusbar::-webkit-scrollbar { display: none; }
  .sb-word, .sb-x, .sb-stat, #sb-model { display: none; }
  .statusbar > * { flex: none; }
  /* E-STOP lives in this bar and must never be the thing that scrolls off. The
     clock, timezone and build string are the least useful pixels on a phone and
     were pushing it (and the AWAKE chip) past the right edge. */
  body.ngm-on .sb-clock, body.ngm-on .sb-tz, body.ngm-on .ng-build { display: none; }
  body.ngm-on .sb-estop { margin-left: auto; }

  /* =====================================================================
   * 2. CHAT CHROME DIET — everything between the top of the screen and the
   * first message that is not the conversation.
   * ===================================================================== */

  /* REPLAY / DIFF: a desk affordance for inspecting a turn. 38px. */
  #view-chat .ng-chat-toolbar { display: none !important; }

  /* The FIRST TOKEN hero: 94px, and its figures are on HOME and in TELEMETRY. */
  #view-chat .sec-hero,
  #view-chat .sec-hero.council-hero { display: none !important; }

  /* The PARSE/RECALL/ROUTE/TOOLS/SYNTH pipeline strip is instrumentation for a
     turn in flight; it held ~60px permanently. It is still on desktop. */
  #view-chat .pipeline { display: none !important; }

  /* The <h1> COUNCIL and the ops chip both duplicate the bottom nav's own
     active COUNCIL label. The header is replaced by #ngm-bar (below). */
  body.ngm-on #view-chat .view-header { display: none !important; }

  /* =====================================================================
   * 3. #ngm-bar — the docked action bar. CHATS · VOICE · MEETING, the three
   * things the operator named as the mobile priority, always reachable with a
   * thumb, never floating on top of the conversation.
   * ===================================================================== */
  #ngm-bar {
    display: flex; align-items: center; gap: 8px;
    padding: 6px max(12px, env(safe-area-inset-left)) 6px max(12px, env(safe-area-inset-right));
    flex: 0 0 auto;
  }
  .ngm-btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 6px;
    min-height: 44px; padding: 0 12px;
    font-family: var(--fm, ui-monospace, monospace);
    font-size: 11px; font-weight: 700; letter-spacing: .12em;
    color: var(--t1, #d7e8ff);
    background: rgba(10, 26, 48, .55);
    border: 1px solid var(--line2, #1d3a5f); border-radius: 12px;
    cursor: pointer; -webkit-tap-highlight-color: transparent;
    white-space: nowrap;
  }
  .ngm-btn:active { transform: scale(.97); }
  .ngm-btn .ngm-ic {
    width: 18px; height: 18px; flex: 0 0 auto;
    stroke: currentColor; stroke-width: 1.6; fill: none;
  }
  /* CHATS takes the left, the title flexes, VOICE + MEETING sit right. */
  #ngm-chats { flex: 0 0 auto; }
  #ngm-title {
    flex: 1 1 auto; min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    font-family: var(--fm, ui-monospace, monospace);
    font-size: 12px; font-weight: 600; letter-spacing: .06em;
    color: var(--t2, #9fb6d4); text-align: center;
  }
  /* VOICE is the hero action — the one G1 bloom in this bar. */
  #ngm-voice {
    color: #041018; background: var(--x-cyan, #2dd9ff);
    border-color: var(--x-cyan, #2dd9ff);
    box-shadow: 0 2px 14px rgba(45, 217, 255, .28);
  }
  /* MEETING is amber only while it is actually recording (signal, not decor). */
  #ngm-meeting[data-rec="1"] {
    color: var(--ng-signal, #ffb02e);
    border-color: color-mix(in srgb, var(--ng-signal, #ffb02e) 55%, transparent);
    background: color-mix(in srgb, var(--ng-signal, #ffb02e) 12%, rgba(6, 13, 26, .9));
  }
  /* The TITLE is what yields on a narrow phone, not the labels. The first
     render dropped the labels at <=480px and left VOICE and MEETING as two
     unlabelled glyphs — the opposite of the brief, which named them the two
     controls that must be obvious. Below 560px the conversation title hides
     (CHATS still shows it) and all three buttons keep their words. */
  @media (max-width: 560px) {
    #ngm-title { display: none; }
    .ngm-btn { padding: 0 10px; font-size: 10px; letter-spacing: .08em; }
    #ngm-bar { gap: 6px; justify-content: space-between; }
    .ngm-btn .ngm-ic { width: 16px; height: 16px; }
  }
  /* Only on the very narrowest phones does the text finally go. */
  @media (max-width: 340px) {
    .ngm-btn .ngm-lbl { display: none; }
  }

  /* The floating pills are replaced by the docked bar — no more overlap.
     (#mtg-fab z=181 was painting across #nvr-pane's text at z=58.) */
  body.ngm-on #mtg-fab,
  body.ngm-on #nvm-fab { display: none !important; }

  /* .cv-bar is the conversations module's own ☰ CHATS strip (~55px, added at
     <=1023 by ng-conversations.js:332). #ngm-bar carries CHATS *and* VOICE and
     MEETING in one 44px row, so the separate strip is now a duplicate. */
  body.ngm-on .cv-bar { display: none !important; }

  /* =====================================================================
   * 3b. THE BANDS ADDED SINCE THE 2026-09-04 PASS. None of these existed
   * when ng-mobile-chat.css reclaimed its ~300px, and none were scoped out
   * of phones, which is how the screen filled back up:
   *     .cv-bar     ~55px   (above)
   *     #nvv-bar    ~40px   HOLD TO TALK / MIC · ASK
   *     .vlane      50-130px  the voice lane — the largest single regression
   *     #nvr-pane   142px on a phone, a 360px COLUMN on a tablet
   * ===================================================================== */

  /* #nvv-bar duplicates VOICE: the full-screen overlay it opens has a far
     bigger hold-to-talk target than this 34px strip. */
  body.ngm-on #nvv-bar { display: none !important; }

  /* The voice lane keeps its header (it carries live research results with
     OPEN / SUMMARY actions) but stops holding 96-320px of rows open. */
  body.ngm-on .vlane { margin: 0 12px 4px !important; }
  body.ngm-on .vlane .vl-rows { max-height: 0; overflow: hidden; transition: max-height .18s ease; }
  body.ngm-on .vlane.ngm-expanded .vl-rows { max-height: 40vh; overflow: auto; }
  @media (prefers-reduced-motion: reduce) {
    body.ngm-on .vlane .vl-rows { transition: none; }
  }

  /* =====================================================================
   * 4. TABS — scrollable, DELIBERATE was clipped mid-word with no hint.
   * ===================================================================== */
  #view-chat .tabs {
    height: 38px; margin: 0 12px 4px; flex: 0 0 auto;
    overflow-x: auto; overflow-y: hidden;
    -webkit-overflow-scrolling: touch; scrollbar-width: none;
  }
  #view-chat .tabs::-webkit-scrollbar { display: none; }
  #view-chat .tab { height: 38px; padding: 0 12px; font-size: 11px; flex: none; }

  /* =====================================================================
   * 5. THE STREAM — the point of the screen. Everything above bought space
   * for this.
   * ===================================================================== */
  #view-chat .stream {
    flex: 1 1 auto; min-height: 0;
    padding: 6px 14px 8px;
    font-size: 15px; line-height: 1.55;
    overscroll-behavior: contain;
  }
  #view-chat .stream .turn,
  #view-chat .stream .msg { max-width: none; }
  #view-chat .stream p { margin: 0 0 .6em; }
  #view-chat .stream pre, #view-chat .stream code { font-size: 12.5px; }
  #view-chat .stream pre { white-space: pre-wrap; overflow-wrap: anywhere; }

  /* =====================================================================
   * 6. VOICE REPLIES pane — 142px of mostly-empty band wedged between the
   * conversation and the composer. Collapsed to its header strip; it expands
   * on tap and whenever it actually holds replies.
   * ===================================================================== */
  /* Two modes to defeat, not one. ng-voice-replies.js picks `sheet` at <=600px
     (fixed, up to 46vh, over the composer) and `dock` above it — and `dock` is
     an absolutely-positioned 360px RIGHT COLUMN inside the chat panel. That
     dock is why the iPad's message stream measured 400px wide inside an 820px
     screen. Both modes are flattened into one in-flow strip. */
  /* .cv-host (the chat tab-panel) is a flex ROW: it holds .cv-side, .cv-main
     and #nvr-pane side by side. At <=1023 .cv-side is already an off-canvas
     absolute drawer, but the un-docked #nvr-pane becomes an in-flow row sibling
     and took 498px of an 820px iPad, crushing .cv-main to 0. Stack instead. */
  /* min-height:0 at every level: without it a column flex item floors at its
     content height, and the stream grew to 1700px inside a 1180px iPad,
     pushing the composer below the fold instead of scrolling. */
  body.ngm-on #view-chat .tab-panel.cv-host {
    flex-direction: column; min-height: 0; overflow: hidden;
  }
  /* .cv-side is only made an off-canvas drawer at <=1023px
     (ng-conversations.js:333-337). Between 1024 and 1200 — iPad Air landscape
     1180, iPad Pro 11" landscape 1194 — it stays an in-flow flex child, and in
     the column layout above it stacks ON TOP of the chat: measured 2174px tall
     at 1180x820, which drove .cv-main to 0 and the stream to 14px. Extend the
     drawer treatment across the whole mobile-shell range so the conversation
     list is always reached via the CHATS button, never in flow. */
  body.ngm-on #view-chat .cv-side {
    position: absolute; z-index: 40; top: 0; bottom: 0; left: 0;
    width: min(84vw, 320px); flex-basis: auto;
    transform: translateX(-103%);
    transition: transform .22s cubic-bezier(.2, 0, 0, 1);
    box-shadow: 0 0 40px rgba(0, 0, 0, .55);
    border-right: 1px solid var(--line2);
  }
  body.ngm-on #view-chat .tab-panel.cv-host.cv-open .cv-side { transform: none; }
  body.ngm-on #view-chat .tab-panel.cv-host.cv-open .cv-veil { display: block; }
  @media (prefers-reduced-motion: reduce) {
    body.ngm-on #view-chat .cv-side { transition: none; }
  }
  body.ngm-on #view-chat .cv-main {
    width: 100%; max-width: none; min-height: 0; min-width: 0;
  }
  /* ng-voice-replies.css:46 reserves the dock column with
     `body.nvr-dock .tab-panel[data-tab="chat"]{padding-right:var(--nvr-w,360px)}`.
     With the pane un-docked that padding is 360px of nothing — it is what held
     the iPad's message column to 460px of 820. */
  body.ngm-on.nvr-dock #view-chat .tab-panel[data-tab="chat"] { padding-right: 0 !important; }

  body.ngm-on #nvr-pane,
  body.ngm-on #nvr-pane[data-mode="sheet"],
  body.ngm-on #nvr-pane[data-mode="dock"] {
    position: static !important;
    width: auto !important; left: auto !important; right: auto !important;
    top: auto !important; bottom: auto !important;
    flex: 0 0 auto;
    max-height: 44px; overflow: hidden;
    margin: 0 12px 4px; border-radius: 12px;
    transition: max-height .18s ease;
  }
  body.ngm-on #nvr-pane.ngm-expanded { max-height: 40vh; overflow: auto; }
  /* The "spoken turns land here — not in the open chat" placeholder is a
     first-run explainer, not a permanent tenant. */
  body.ngm-on #nvr-pane .nvr-empty { display: none; }
  body.ngm-on #nvr-pane.ngm-expanded .nvr-empty { display: block; }
  @media (prefers-reduced-motion: reduce) {
    body.ngm-on #nvr-pane { transition: none; }
  }

  /* =====================================================================
   * 7. THE COMPOSER — one row. ng-mobile-revamp.js moves the secondary
   * controls into #ngm-sheet behind the `+` button; these rules lay out what
   * is left: [+] [input] [send].
   * ===================================================================== */
  body.ngm-on #view-chat .composer {
    display: flex; flex-wrap: nowrap; align-items: center; gap: 8px;
    padding: 8px; flex: 0 0 auto;
    margin: 0 12px calc(8px + env(safe-area-inset-bottom));
  }
  body.ngm-on #view-chat .composer > .composer-input {
    order: 2; flex: 1 1 auto; min-width: 0; width: auto;
    height: 44px;
    font-size: 16px;   /* 16px exactly: anything smaller makes iOS zoom on focus */
  }
  body.ngm-on #view-chat .composer > .composer-send {
    order: 3; flex: 0 0 44px; width: 44px; height: 44px; margin: 0;
  }
  #ngm-plus {
    order: 1; flex: 0 0 44px; width: 44px; height: 44px;
    display: grid; place-items: center;
    font-size: 20px; line-height: 1;
    color: var(--x-cyan, #2dd9ff);
    background: rgba(10, 26, 48, .55);
    border: 1px solid var(--line2, #1d3a5f); border-radius: 12px;
    cursor: pointer; -webkit-tap-highlight-color: transparent;
  }
  #ngm-plus[aria-expanded="true"] {
    color: #041018; background: var(--x-cyan, #2dd9ff); border-color: var(--x-cyan, #2dd9ff);
  }

  /* The `+` sheet: everything the composer used to wear on its sleeve. */
  #ngm-sheet {
    position: fixed; left: 0; right: 0;
    bottom: calc(64px + env(safe-area-inset-bottom));
    z-index: 120;
    display: none;
    flex-wrap: wrap; gap: 8px;
    padding: 12px max(12px, env(safe-area-inset-left))
             14px max(12px, env(safe-area-inset-right));
    background: rgba(4, 10, 20, .96);
    backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
    border-top: 1px solid var(--line2, #1d3a5f);
    box-shadow: 0 -8px 32px rgba(0, 0, 0, .5);
  }
  #ngm-sheet.open { display: flex; }
  /* Adopted children keep their own identity but get a real touch target. */
  #ngm-sheet > * {
    min-height: 44px !important; height: auto !important;
    font-size: 11px !important; padding: 0 12px !important;
    display: inline-flex !important; align-items: center; gap: 6px;
    flex: 0 0 auto;
  }
  /* …and so do NESTED controls. The `> *` rule above only reaches direct
     children: the model chip arrives wrapped in a bare <span>, so the span got
     its 44px while the button inside stayed 111x22 (measured). */
  #ngm-sheet button,
  #ngm-sheet [role="button"] {
    min-height: 44px !important; min-width: 44px;
  }

  /* =====================================================================
   * 8. TOUCH TARGETS — Apple's 44px minimum. The audit found 17 controls
   * under 40px in the chat view on a phone (vl-toggle was 21x18).
   * ===================================================================== */
  body.ngm-on #view-chat button,
  body.ngm-on .vl-toggle, body.ngm-on .vl-kill,
  body.ngm-on #nvr-pane button { min-height: 36px; }
  body.ngm-on .bn-btn { min-height: 48px; min-width: 48px; }

  /* The VOICE overlay and MEETING stage are full-screen surfaces OUTSIDE
     #view-chat, so the rule above never reached them. Measured on an iPhone
     15 Pro: MEETING's per-recording play/delete were 36x36, and inside the
     voice overlay the voice-lane's OPEN and SUMMARY were 43x20 and 64x20 —
     a delete button you can mis-tap is the worst of these. */
  /* CAUTION, learned the hard way: `body.ngm-on #nvm-root button` (0,2,1)
     OUTRANKS ng-voice-mobile.css's own `#nvm-top button{min-height:44px}`
     (0,1,1), so a 36px floor here does not raise small buttons — it SHRINKS
     the overlay's close/mute/conversation controls from 44 to 36. The overlay
     is full-screen and has the room, so it gets the full 44. */
  body.ngm-on #nvm-root button { min-height: 44px; }
  /* Inline row actions inside the lane and the replies strip keep 36px — four
     of them share a row and 44 each would double every row's height. Listed
     AFTER the rule above so they win at equal specificity. */
  body.ngm-on .vlane button,
  body.ngm-on #nvr-pane button { min-height: 36px; }
  body.ngm-on .mtg-stage .mtg-ico { min-height: 40px; min-width: 40px; }
  body.ngm-on .mtg-stage .mtg-ico.del { min-height: 44px; min-width: 44px; }
  /* The rule above is `body.ngm-on #view-chat button` (0,2,1) and outranks a
     bare `.ngm-btn` (0,1,0) — it was silently capping the CHATS/VOICE/MEETING
     buttons at 36px. Match its specificity so the bar keeps its 44px. */
  body.ngm-on #ngm-bar .ngm-btn { min-height: 44px; min-width: 44px; }
  /* The CHATS drawer is the "see previous chats" surface, so its primary
     targets — a conversation row, a group header, NEW and MERGE — get the full
     44px. The per-row micro-actions (PIN/REN/EXP/DEL) stay at 36px: four of
     them share one row, and 44px each would double the height of every entry
     in the list the operator is trying to scan. */
  body.ngm-on .cv-side .cv-item,
  body.ngm-on .cv-side .cv-gh,
  body.ngm-on .cv-side .cv-new,
  body.ngm-on .cv-side .cv-merge { min-height: 44px; }
  body.ngm-on #view-chat .tabs .tab { min-height: 44px; height: 44px; }
  body.ngm-on #view-chat .tabs { height: 44px; }

  /* Ghost toasts sat on the composer chips. Lift them clear of the new stack. */
  /* Stack below the toast, bottom-up: nav 64 + composer 62 + its 8 margin +
     the collapsed voice-replies strip 44 + 4 = 182. 130px put the toast on top
     of that strip in the render. */
  body.ngm-on .ghosts {
    left: 10px; right: 10px;
    bottom: calc(190px + env(safe-area-inset-bottom));
    align-items: stretch;
  }
  body.ngm-on .ghost-note { max-width: none; }
  body.ngm-on .jump-chip { bottom: 132px; }
}

/* ===========================================================================
 * LAPTOP / SHORT-DESKTOP DENSITY (2026-09-06)
 *
 * The desktop layout was tuned on tall monitors and assumes height it does not
 * have on a laptop. MEASURED on the real Apple logical resolutions:
 *
 *   MacBook Air 13"  1470x956   stream 278px = 29%   (composer 142, chrome 216)
 *   MacBook 14"/15"  1512x982   stream 304px = 31%
 *   iPad Pro landsc. 1366x1024  stream 354px = 35%
 *   MacBook Pro 16"  1728x1117  stream 519px = 46%
 *   1080p            1920x1080  stream 482px = 45%
 *   1440p / ultrawide           stream 887px = 62%  <- healthy, left alone
 *
 * Two separate causes:
 *   HEIGHT — 216px of chrome above the stream (REPLAY/DIFF 38 + header 56 +
 *   tabs 27 + FIRST TOKEN hero 94) plus a 142px composer.
 *   WIDTH  — on a 15" the conversation got 532px while the telemetry rail (300)
 *   and the voice dock (360) took 660 between them.
 *
 * Tiered by HEIGHT, so a 16" keeps more instrumentation than a 13" and the
 * 1440p/ultrawide desktops are untouched. Nothing here applies below 1201px —
 * that range is the mobile shell above.
 * ------------------------------------------------------------------------ */

/* Tier 1 — every laptop-height desktop. Nothing is removed. */
@media (min-width: 1201px) and (max-height: 1150px) {
  /* The composer is capped to the 720px reading measure (mockup-v11.html:1989)
     and centred. That cap is right for message text but it forced ELEVEN
     controls onto three rows — 142px. The reading measure still governs the
     messages; only the control strip is allowed to be wider. */
  #view-chat .composer {
    width: min(100%, calc(var(--ng-chat-measure, var(--chat-measure, 720px)) + 360px));
  }
  /* The voice dock's 360px is a lot of a 1470px screen. 280 keeps it usable and
     hands 80px back to the conversation. --nvr-w is set inline on <body> by
     ng-voice-replies.js:199, so this needs !important to win. */
  body.nvr-dock { --nvr-w: 280px !important; }
  #view-chat .view-header { padding-top: 10px; padding-bottom: 6px; }
}

/* Tier 2 — 13"/15" MacBooks and iPad Pro landscape. */
@media (min-width: 1201px) and (max-height: 1050px) {
  /* 94px, and its figures are also on HOME and in TELEMETRY. On a cold load
     most of them render as em-dashes. */
  #view-chat .sec-hero.council-hero { display: none; }
}

/* Tier 3 — the shortest laptops only (13" 956, 15" 982). */
@media (min-width: 1201px) and (max-height: 1000px) {
  /* REPLAY / DIFF is a turn-inspection affordance. It stays on every screen
     1000px and taller; here 38px of permanent chrome is worth more as chat. */
  #view-chat .ng-chat-toolbar { display: none; }
}

/* ---------------------------------------------------------------------------
 * FILES view — the same tablet gap as the chat view. ng-files.js:147 collapses
 * the files layout at <=720px (`.f-sidebar,.f-tabs-aside{display:none}`), so at
 * 820px the iPad keeps the desktop three-column layout. Measured 2026-09-06:
 * `.f-sidebar` held 220px while `.f-tabs` and `.f-tabs-aside` were squeezed to
 * ZERO width at x=820 with their buttons (f-tab, #f-empty-trash) spilling off
 * the right edge — visible, not hidden. Mirror the ≤720px intent up to 1024px.
 * ------------------------------------------------------------------------- */
@media (min-width: 721px) and (max-width: 1200px) {
  #view-files .f-files { grid-template-columns: 1fr; }
  #view-files .f-sidebar,
  #view-files .f-tabs-aside { display: none; }
  #view-files .f-c-time { display: none; }
  #view-files .f-tabs { overflow-x: auto; scrollbar-width: none; }
  #view-files .f-tabs::-webkit-scrollbar { display: none; }
  #view-files .f-tab { flex: none; }
}

/* ---------------------------------------------------------------------------
 * Phone landscape and short viewports: the action bar and tabs are the first
 * things to go when there is no vertical room at all.
 * ------------------------------------------------------------------------- */
/* MEASURED 2026-09-06, iPhone landscape 852x393: the stream was 57px — 15% of
 * the screen — because the portrait chrome costs a flat ~222px (statusbar 48 +
 * bar 56 + composer 62 + nav 64) and in landscape that is 57% of the height.
 * Everything below buys height back; nothing is removed that you cannot still
 * reach (the nav stays, the bar stays, only their padding shrinks). */
@media (max-width: 1200px) and (max-height: 460px) {
  body.ngm-on #view-chat .tabs { display: none; }

  /* statusbar 48 -> 36 (E-STOP still lives here, so it is shrunk, not hidden) */
  body.ngm-on .statusbar { height: calc(36px + env(safe-area-inset-top)); }
  body.ngm-on .app { padding-top: calc(36px + env(safe-area-inset-top)); }
  body.ngm-on .view.active { top: calc(36px + env(safe-area-inset-top)); }

  /* nav 64 -> 46, labels dropped; the icons and the active colour still read */
  body.ngm-on .bottomnav { height: calc(46px + env(safe-area-inset-bottom)); }
  body.ngm-on .bn-btn { height: 42px; min-height: 42px; gap: 0; font-size: 0; }
  body.ngm-on .bn-btn svg { width: 22px; height: 22px; }
  body.ngm-on .app { padding-bottom: calc(46px + env(safe-area-inset-bottom)); }
  body.ngm-on .view.active { bottom: calc(46px + env(safe-area-inset-bottom)); }

  /* action bar 56 -> 40, composer 62 -> 50 */
  body.ngm-on #ngm-bar { padding-top: 2px; padding-bottom: 2px; gap: 6px; }
  body.ngm-on .ngm-btn { min-height: 36px; }
  body.ngm-on #view-chat .composer { padding: 4px 6px; margin: 0 10px 4px; }
  body.ngm-on #view-chat .composer > .composer-input,
  body.ngm-on #view-chat .composer > .composer-send,
  body.ngm-on #ngm-plus { height: 40px; }
  body.ngm-on #view-chat .composer > .composer-send,
  body.ngm-on #ngm-plus { flex-basis: 40px; width: 40px; }

  /* the collapsed voice strips are the first thing to go when there is no room */
  body.ngm-on #nvr-pane:not(.ngm-expanded),
  body.ngm-on .vlane:not(.ngm-expanded) { display: none; }

  body.ngm-on .ghosts { bottom: calc(100px + env(safe-area-inset-bottom)); }
}
