/* ============================================================================
   Aecos Mobile — mobile.css (owned by aecos-mobile minion)

   THE RULES OF THIS FILE — read before editing:
   1. Every rule lives inside the phone media block
      `(max-width: 768px), ((pointer: coarse) and (max-height: 500px))`
      — portrait phones by width, LANDSCAPE phones by coarse pointer + short
      viewport (R6; an 844×390 phone escapes the width clause). Nothing
      outside a media block except comments. This file can therefore NEVER
      affect desktop — that invariant is the reason it exists (the 2026-05-20
      mobile rollback was caused by responsive overrides in styles.css).
      JS twin: mqIsPhone() in mobile.jsx / window.AECOS_MOBILE.isPhone().
   2. Until public launch, workspace rules are additionally gated on
      `html.aecos-mobile-preview` (set from localStorage `aecos_mobile_preview`
      by mobile.jsx). Public phones keep the desktop gate; preview devices get
      the mobile workspace. Launch = remove the gate class from selectors.
   3. Only `--m-*` custom properties are DEFINED here. Existing design tokens
      (--bg, --ink-*, --indigo, --duration-*, --ease-*, --f-*) are consumed,
      never redefined — so theme + density keep working on mobile for free.
   4. New classes use the `.m-` prefix. Other minions' classes may receive
      layout-only adaptation (columns, padding, sizing) — never identity
      changes (colors, fonts, brand).
   5. This file loads AFTER styles.css (see build-bundle.py + Aecos.html
      integration diffs in .claude/docs/mobile-plan.md §6).
   ============================================================================ */

@media (max-width: 768px), ((pointer: coarse) and (max-height: 500px)) {

  /* ── Mobile tokens ──────────────────────────────────────────────────────── */
  html.aecos-mobile-preview {
    --m-pad: 16px;            /* page gutter */
    --m-gap: 12px;            /* gap between cards / list items */
    --m-radius: 12px;         /* card + sheet corner radius */
    --m-touch: 44px;          /* min touch target (iOS HIG / WCAG 2.5.5) */
    --m-tabbar-h: 64px;
    --m-header-h: 52px;
    --m-safe-bottom: env(safe-area-inset-bottom, 0px);
    --m-safe-top: env(safe-area-inset-top, 0px);
    --m-sheet-z: 9000;        /* above .page content, below toasts */
    --m-tabbar-z: 8500;
  }

  /* ── Gate lift + viewport scroll-lock (preview only) ────────────────────────
     styles.css hides #root on operational routes at ≤768px in two places:
       12563: `#root { display:none }` (+ body.allow-mobile override)
       17736: `body:not(.is-landing) #root { display:none }`
     This out-cascades both (later file + higher specificity + !important —
     the same trick body.allow-mobile already uses).

     SCROLL-LOCK (founder bugs #1 + #2, 2026-06-10): styles.css's landing
     unlock (`html { height:auto; overflow:visible }` at ~17768) is
     UNCONDITIONAL at ≤768px, which collapses the html→body→#root height
     chain: body/`#root` `height:100%` resolve to auto, so `.m-page`/`.page`
     never get a bounded height → their overflow-y:auto can't scroll
     ("not able to scroll"). Meanwhile body's overflow:hidden propagates to
     the viewport, which iOS Safari IGNORES for touch panning when content
     overflows → the whole document pans sideways ("slides off the screen").

     Fix: `position:fixed; inset:0` on body — for fixed elements percentage
     heights resolve against the viewport, so the height chain is restored
     WITHOUT touching styles.css's html rule (the landing keeps document
     scroll), and a fixed body is the one scroll-lock iOS actually honors:
     the document can never pan in either axis. All scrolling happens in
     designated inner containers (.m-page, .page, sheet panels) — founder
     rule: content bound to the screen; only intentional gadgets scroll. */
  /* ⚠️ html:not(.is-landing) guard on the four lock rules below — DO NOT drop.
     This is part of the Chrome-mobile COLD-LOAD scroll fix (2026-07-10): on a
     cold load of the public landing, html.is-landing is set pre-paint by the
     <head> script but body.is-landing historically only landed at
     DOMContentLoaded (after the multi-MB bundle parsed) — so body:not(.is-landing)
     matched during the whole first paint and THIS position:fixed lock froze the
     document; Chrome for Android then latched "not scrollable" and the landing
     couldn't touch-scroll until a route change. html carries the landing truth
     from before first paint, so keying the lock on html:not(.is-landing) makes
     it impossible for the preview lock to engage on a landing cold load, even
     if the body class is late (or the body-boot script in Aecos.html/app.html
     is ever merge-dropped). Behavior is unchanged whenever html and body agree
     (they always do post-mount — the App effect toggles both). */
  html.aecos-mobile-preview:not(.is-landing) body:not(.is-landing) {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    overflow: hidden;
    overscroll-behavior: none;
    /* Vertical pans + pinch only at the document level. Inner horizontal
       gadgets (.m-chips, table wraps) re-allow pan-x on themselves — an
       ancestor's touch-action doesn't restrict a descendant scroll container. */
    touch-action: pan-y pinch-zoom;
    background: var(--bg);
  }
  html.aecos-mobile-preview:not(.is-landing) body:not(.is-landing) #root {
    display: flex !important;
    height: 100%;
    max-width: 100%;
    overflow: hidden;
  }
  html.aecos-mobile-preview:not(.is-landing) body:not(.is-landing) #mobile-gate {
    display: none !important; /* element currently absent; guard anyway */
  }
  /* Auth route under the lock: .auth-screen has min-height:100vh and no
     scroller of its own — give it one so sign-in/sign-up forms taller than
     the viewport stay reachable. */
  html.aecos-mobile-preview:not(.is-landing) body:not(.is-landing) .auth-screen {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
  }

  /* ── App shell reshaping (preview only) ─────────────────────────────────────
     Hide the desktop chrome the mobile frame replaces. The hamburger-drawer
     pattern (.mobile-nav-trigger + .sidebar.mobile-open) is superseded by the
     bottom tab bar. */
  html.aecos-mobile-preview .sidebar,
  html.aecos-mobile-preview .sidebar-collapse-btn,
  html.aecos-mobile-preview .mobile-nav-trigger,
  html.aecos-mobile-preview .mobile-nav-scrim {
    display: none !important;
  }
  html.aecos-mobile-preview .app-right {
    margin-left: 0 !important;
    width: 100%;
  }
  /* (.topbar padding rule removed — .topbar is display:none on mobile below, so
     it was dead.) */
  /* Reserve room for the fixed tab bar so page content never hides under it. */
  html.aecos-mobile-preview .page {
    padding: var(--m-pad);
    padding-bottom: calc(var(--m-tabbar-h) + var(--m-safe-bottom) + var(--m-pad));
  }

  /* ── .m-tabbar — bottom tab bar (MobileTabBar in mobile.jsx) ──────────────── */
  .m-tabbar {
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: var(--m-tabbar-z, 8500);
    display: flex;
    align-items: stretch;
    height: calc(var(--m-tabbar-h, 64px) + var(--m-safe-bottom, 0px));
    padding-bottom: var(--m-safe-bottom, 0px);
    background: var(--bg-card);
    border-top: 1px solid var(--line);
    /* Subtle upward lift so the bar reads as floating over the page. No token
       exists for an UPWARD shadow (--shadow-* are all drop shadows); this raw
       rgba is intentional and stays near-invisible on both light + dark. */
    box-shadow: 0 -6px 20px -16px rgba(0, 0, 0, 0.32);
  }
  .m-tabbar__item {
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    min-height: var(--m-touch, 44px);
    background: none;
    border: none;
    padding: 0;
    font-size: 10.5px;
    font-weight: 550;
    letter-spacing: 0.01em;
    color: var(--ink-4);
    -webkit-tap-highlight-color: transparent;
    transition: color var(--duration-fast) var(--ease-in-out);
  }
  .m-tabbar__item--active { color: var(--indigo); }
  .m-tabbar__item:active  { color: var(--ink-2); }
  /* Center (Chat) tab gets a subtle accent ring so the AI reads as primary. */
  .m-tabbar__item--accent .m-tabbar__icon {
    display: flex; align-items: center; justify-content: center;
    width: 34px; height: 34px;
    border-radius: 50%;
    background: var(--indigo-soft);
    color: var(--indigo);
  }
  @media (max-width: 380px) {
    .m-tabbar__item { font-size: 9.5px; }
  }

  /* ── .m-sheet — reusable bottom sheet (MobileSheet in mobile.jsx) ─────────── */
  .m-sheet {
    position: fixed; inset: 0;
    z-index: var(--m-sheet-z, 9000);
    display: flex; flex-direction: column; justify-content: flex-end;
  }
  .m-sheet__scrim {
    position: absolute; inset: 0;
    /* Raw rgba is the desktop scrim convention (styles.css modal/drawer overlays
       use rgba(0,0,0,.35–.5) directly — there is no --scrim token). The light
       backdrop blur matches those desktop overlays. */
    background: rgba(0, 0, 0, 0.45);
    -webkit-backdrop-filter: blur(2px);
    backdrop-filter: blur(2px);
    animation: m-scrim-in var(--duration-base) var(--ease-in-out);
  }
  .m-sheet__panel {
    position: relative;
    width: 100%; max-width: 100%;
    box-sizing: border-box;
    background: var(--bg-card);
    border-radius: 16px 16px 0 0;
    border-top: 1px solid var(--line);
    padding: 8px var(--m-pad) calc(20px + var(--m-safe-bottom, 0px));
    max-height: 82dvh;
    overflow-y: auto; overflow-x: hidden;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain; /* sheet scroll never leaks to the page */
    touch-action: pan-y;
    animation: m-sheet-up var(--duration-slow) var(--ease-out);
  }
  .m-sheet__handle {
    width: 40px; height: 5px;
    border-radius: 3px;
    background: var(--line-strong);
    margin: 6px auto 14px;
    position: relative;
  }
  /* R6 swipe-to-dismiss: generous invisible grab zone around the 40×5 bar so
     the drag reliably engages from the handle on first touch. */
  .m-sheet__handle::after {
    content: ""; position: absolute; inset: -14px -80px;
  }
  .m-sheet__title {
    font-size: 16px; font-weight: 650; color: var(--ink);
    margin-bottom: 10px;
  }
  @keyframes m-scrim-in { from { opacity: 0; } to { opacity: 1; } }
  @keyframes m-sheet-up { from { transform: translateY(100%); } to { transform: translateY(0); } }
  @media (prefers-reduced-motion: reduce) {
    .m-sheet__scrim, .m-sheet__panel { animation: none; }
  }

  /* ── More sheet (MobileMoreSheet) — sidebar groups as a tap list ──────────── */
  .m-more__section {
    font-size: 10.5px; font-weight: 650; letter-spacing: 0.06em;
    text-transform: uppercase; color: var(--ink-5);
    padding: 14px 2px 6px;
  }
  .m-more__item {
    display: flex; align-items: center; gap: 12px;
    width: 100%;
    min-height: var(--m-touch, 44px);
    padding: 10px 2px;
    background: none; border: none;
    border-bottom: 1px solid var(--line-soft);
    font-size: 14.5px; color: var(--ink-2);
    text-align: left;
    -webkit-tap-highlight-color: transparent;
  }
  .m-more__item:last-child { border-bottom: none; }
  .m-more__item--active { color: var(--indigo); font-weight: 600; }
  .m-more__item-icon { display: flex; color: var(--ink-4); }
  .m-more__item--active .m-more__item-icon { color: var(--indigo); }
  .m-more__item--danger { color: var(--bad); }
  .m-more__item--danger .m-more__item-icon { color: var(--bad); }
  /* Account block — profile row pinned at the TOP of the sheet (founder bug
     #3: profile / Settings / sign-out must be visible without scrolling). */
  .m-more__profile {
    display: flex; align-items: center; gap: 12px;
    width: 100%;
    min-height: var(--m-touch, 44px);
    padding: 8px 2px 12px;
    background: none; border: none;
    border-bottom: 1px solid var(--line-soft, var(--line));
    text-align: left;
    -webkit-tap-highlight-color: transparent;
  }
  .m-more__avatar {
    width: 40px; height: 40px; flex-shrink: 0;
    border-radius: 50%;
    object-fit: cover;       /* uploaded photos: crop, never blow out layout */
    background: var(--indigo-soft, var(--bg-elev));
  }
  .m-more__avatar--initials {
    display: flex; align-items: center; justify-content: center;
    font-size: 14px; font-weight: 700; color: var(--indigo);
  }
  .m-more__profile-meta { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
  .m-more__profile-name {
    font-size: 14.5px; font-weight: 650; color: var(--ink);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .m-more__profile-sub {
    font-size: 12px; color: var(--ink-4);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .m-more__profile-chev { color: var(--ink-5); flex-shrink: 0; display: flex; }

  /* ── Desktop-only notice (MobileDesktopOnlyNotice) ────────────────────────── */
  .m-desktop-only {
    display: flex; flex-direction: column; align-items: center;
    text-align: center;
    padding: 56px var(--m-pad);
    color: var(--ink-3);
  }
  .m-desktop-only__icon { color: var(--ink-5); margin-bottom: 14px; }
  .m-desktop-only__title { font-size: 16px; font-weight: 600; color: var(--ink); margin-bottom: 6px; }
  .m-desktop-only__body  { font-size: 13.5px; line-height: 1.55; max-width: 34ch; }

  /* ── .m-header — slim fixed top bar (MobileHeader) ────────────────────────── */
  .m-header {
    position: fixed;
    top: 0; left: 0; right: 0;
    z-index: var(--m-tabbar-z, 8500);
    display: flex; align-items: center; gap: 10px;
    height: calc(var(--m-header-h, 52px) + var(--m-safe-top, 0px));
    padding: var(--m-safe-top, 0px) var(--m-pad, 16px) 0;
    background: var(--bg-card);
    border-bottom: 1px solid var(--line);
    box-shadow: var(--shadow-sm); /* theme-aware drop shadow — separates from scrolling content */
  }
  .m-header__mark { display: flex; width: 20px; height: 20px; color: var(--ink-2); flex-shrink: 0; }
  .m-header__mark svg { width: 100%; height: 100%; }
  .m-header__back {
    display: flex; align-items: center; justify-content: center;
    width: 32px; height: 32px; margin-left: -8px; flex-shrink: 0;
    background: none; border: none; color: var(--ink-2); padding: 0;
    -webkit-tap-highlight-color: transparent;
  }
  .m-header__title {
    flex: 1 1 0; min-width: 0;
    font-size: 16px; font-weight: 650; color: var(--ink);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .m-header__bell {
    position: relative;
    display: flex; align-items: center; justify-content: center;
    width: var(--m-touch, 44px); height: var(--m-touch, 44px);
    margin-right: -10px; flex-shrink: 0;
    background: none; border: none; color: var(--ink-3); padding: 0;
    -webkit-tap-highlight-color: transparent;
  }
  .m-header__badge {
    position: absolute; top: 7px; right: 6px;
    min-width: 15px; height: 15px; padding: 0 3px;
    border-radius: 8px; background: var(--bad);
    color: #fff; font-size: 9.5px; font-weight: 700; line-height: 15px;
    text-align: center;
  }

  /* ── .m-page — scrollable page container for full-page mobile routes ──────── */
  /* Full-page routes render directly inside #root (height:100%, overflow
     hidden) — the page itself owns scrolling, padded clear of the fixed
     header + tab bar. Founder rule #1: everything bound within the screen. */
  .m-page {
    flex: 1 1 auto;
    width: 100%; max-width: 100%;
    min-height: 0;
    overflow-y: auto; overflow-x: hidden;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;   /* never chain into (a pannable) document */
    touch-action: pan-y pinch-zoom; /* page itself never pans sideways */
    background: var(--bg);
    padding: calc(var(--m-header-h, 52px) + var(--m-safe-top, 0px) + var(--m-pad, 16px))
             var(--m-pad, 16px)
             calc(var(--m-tabbar-h, 64px) + var(--m-safe-bottom, 0px) + var(--m-pad, 16px));
  }
  /* break-word (not anywhere): break only when a token can't fit, at the
     nearest opportunity — `anywhere` shattered currency/IDs/hours mid-glyph
     ($1,2 / 00.00, PNQ / -104, 7 / 95h). min-width:0 still lets flex/grid
     children shrink, which is what the universal rule is really here for. */
  .m-page * { min-width: 0; overflow-wrap: break-word; }
  .m-page > * { max-width: 100%; }

  /* ── Shared primitives ────────────────────────────────────────────────────── */
  .m-section-label {
    font-size: 11px; font-weight: 700; letter-spacing: 0.07em;
    text-transform: uppercase; color: var(--ink-4);
    margin: 18px 0 8px;
  }
  .m-card {
    display: block; width: 100%; max-width: 100%;
    background: var(--bg-card);
    border: 1px solid var(--line);
    border-radius: var(--m-radius, 12px);
    padding: 14px 16px;
    margin-bottom: var(--m-gap, 12px);
    box-sizing: border-box;
  }
  .m-card--tap { text-align: left; cursor: pointer; -webkit-tap-highlight-color: transparent; }
  .m-card--ok { color: var(--ok); font-weight: 600; font-size: 14px; }
  .m-empty { font-size: 13px; color: var(--ink-4); padding: 14px 2px; line-height: 1.5; }
  .m-btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 6px;
    min-height: var(--m-touch, 44px);
    padding: 0 16px;
    border-radius: 10px;
    background: var(--bg-elev); border: 1px solid var(--line);
    font-size: 14px; font-weight: 600; color: var(--ink-2);
    -webkit-tap-highlight-color: transparent;
  }
  .m-btn--primary { background: var(--indigo); border-color: var(--indigo); color: #fff; }
  .m-btn--danger  { color: var(--bad); }
  .m-btn--block   { display: flex; width: 100%; margin-top: 16px; }
  .m-select, .m-input {
    display: block; width: 100%; max-width: 100%;
    min-height: var(--m-touch, 44px);
    padding: 0 12px; margin-bottom: 10px;
    border-radius: 10px; border: 1px solid var(--line);
    background: var(--bg); color: var(--ink);
    font-size: 16px; /* ≥16px prevents iOS zoom-on-focus */
    font-family: inherit;
    box-sizing: border-box;
  }
  .m-select:focus, .m-input:focus { outline: none; border-color: var(--indigo); box-shadow: 0 0 0 3px var(--indigo-soft); }
  .m-search__input:focus { box-shadow: 0 0 0 3px var(--indigo-soft); }

  /* ── Interaction states — pressed / disabled / keyboard focus ───────────────
     Unifies tactile feedback across every tappable .m-* surface. The desktop
     app leans on :hover for this; touch has no hover, so the press-state IS the
     whole affordance. Tokens only → correct on light / mid / dark for free. */
  .m-card--tap, .m-action, .m-gantt__pcard, .m-more__item, .m-more__profile,
  .m-set__row, .m-notif, .m-gantt__back, .m-ph__head, .m-stat, .m-header__bell,
  .m-header__back {
    transition: background-color var(--duration-fast) var(--ease-in-out),
                border-color var(--duration-fast) var(--ease-in-out),
                color var(--duration-fast) var(--ease-in-out);
  }
  /* Elevated cards: press lifts them onto the next surface tone + a firmer edge. */
  .m-card--tap:active, .m-action:active, .m-gantt__pcard:active {
    background: var(--bg-elev); border-color: var(--line-strong);
  }
  /* Full-bleed list rows: press sinks to the recessed tone. */
  .m-more__item:active, .m-more__profile:active, .m-set__row:active,
  .m-notif:active, .m-gantt__back:active, .m-ph__head:active {
    background: var(--bg-sunk, var(--bg-elev));
  }
  .m-header__bell:active, .m-header__back:active { color: var(--ink); }
  /* Buttons: subtle depress + darkened primary; disabled dims and locks. */
  .m-btn {
    transition: background-color var(--duration-fast) var(--ease-in-out),
                border-color var(--duration-fast) var(--ease-in-out),
                transform var(--duration-fast) var(--ease-out),
                opacity var(--duration-fast) var(--ease-in-out);
  }
  .m-btn:active { transform: scale(0.975); }
  .m-btn:not(.m-btn--primary):not(.m-btn--danger):active { background: var(--bg-sunk, var(--bg-elev)); }
  .m-btn--primary:active { background: color-mix(in srgb, var(--indigo) 84%, black); border-color: color-mix(in srgb, var(--indigo) 84%, black); }
  .m-btn:disabled, .m-btn[disabled] { opacity: 0.45; transform: none; pointer-events: none; }
  .m-chip { transition: background-color var(--duration-fast) var(--ease-in-out), border-color var(--duration-fast) var(--ease-in-out); }
  .m-chip:active:not(.m-chip--on) { background: var(--bg-elev); border-color: var(--line-strong); }
  /* Text-link actions: press fades. */
  .m-brief__more:active, .m-ph__more:active, .m-ph__edit:active,
  .m-set__back:active { opacity: 0.6; }
  /* Keyboard focus (a11y). Touch presses don't trigger :focus-visible, so this
     never appears on tap — it's purely for keyboard / switch-control users.
     Inset offset keeps the ring clear of the screen edge on the fixed bars. */
  .m-tabbar__item:focus-visible, .m-btn:focus-visible, .m-chip:focus-visible,
  .m-more__item:focus-visible, .m-more__profile:focus-visible, .m-set__row:focus-visible,
  .m-card--tap:focus-visible, .m-action:focus-visible, .m-gantt__pcard:focus-visible,
  .m-header__bell:focus-visible, .m-header__back:focus-visible, .m-chat__close:focus-visible,
  .m-notif:focus-visible, .m-gantt__back:focus-visible, .m-ph__head:focus-visible,
  .m-set__back:focus-visible {
    outline: 2px solid var(--indigo); outline-offset: -2px;
  }

  /* ── Today (MobileHomePage) ───────────────────────────────────────────────── */
  .m-home__date { font-size: 12px; color: var(--ink-4); }
  .m-home__greeting { font-size: 24px; font-weight: 700; color: var(--ink); margin: 4px 0 6px; line-height: 1.2; }
  .m-urgent { display: flex; align-items: flex-start; gap: 11px; }
  .m-urgent__dot { width: 8px; height: 8px; border-radius: 50%; margin-top: 5px; flex-shrink: 0; }
  .m-urgent__body { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
  .m-urgent__title {
    font-size: 14px; font-weight: 600; color: var(--ink);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .m-urgent__sub { font-size: 12px; }
  .m-urgent__chev { color: var(--ink-5); flex-shrink: 0; margin-top: 3px; }
  .m-brief__label { display: flex; align-items: center; gap: 5px; margin: 0 0 8px; }
  .m-brief__text {
    font-size: 13.5px; color: var(--ink-2); line-height: 1.6;
    max-height: 150px; overflow: hidden;
    -webkit-mask-image: linear-gradient(to bottom, black 80%, transparent 100%);
    mask-image: linear-gradient(to bottom, black 80%, transparent 100%);
  }
  /* Expanded: drop the clamp + fade so the full briefing is readable. */
  .m-brief.is-open .m-brief__text {
    max-height: none; overflow: visible;
    -webkit-mask-image: none; mask-image: none;
  }
  .m-brief__more {
    margin-top: 6px; padding: 8px 0; min-height: 36px;
    display: inline-flex; align-items: center;
    background: none; border: none;
    font-size: 12.5px; font-weight: 600; color: var(--indigo);
    -webkit-tap-highlight-color: transparent; cursor: pointer;
  }
  .m-home__stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; margin-top: 16px; }
  .m-stat {
    display: flex; flex-direction: column; align-items: center; gap: 4px;
    background: var(--bg-card); border: 1px solid var(--line);
    border-radius: var(--m-radius, 12px); padding: 13px 8px;
    text-align: center; min-width: 0;
  }
  .m-stat__icon { color: var(--indigo); display: flex; }
  .m-stat__value { font-size: 22px; font-weight: 700; color: var(--ink); line-height: 1; }
  .m-stat__label { font-size: 10.5px; color: var(--ink-4); line-height: 1.3; }
  .m-home__actions { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
  .m-action {
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px;
    min-height: 64px; padding: 10px 4px;
    background: var(--bg-card); border: 1px solid var(--line);
    border-radius: var(--m-radius, 12px);
    font-size: 12px; font-weight: 600; color: var(--ink-2);
    -webkit-tap-highlight-color: transparent;
  }
  .m-action svg { color: var(--indigo); }
  @media (max-width: 380px) {
    .m-home__greeting { font-size: 21px; }
    .m-stat__value { font-size: 19px; }
  }
  .m-item__title { font-size: 17px; font-weight: 700; color: var(--ink); line-height: 1.35; margin-bottom: 12px; }
  .m-item__row { display: flex; align-items: center; gap: 7px; font-size: 13px; color: var(--ink-3); margin-bottom: 8px; }
  .m-item__notes { font-size: 13px; color: var(--ink-2); line-height: 1.55; margin-top: 10px; }

  /* ── Projects (MobileProjectsPage + peek sheet) ───────────────────────────── */
  .m-search {
    position: relative; margin-bottom: 10px;
  }
  .m-search__icon { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: var(--ink-5); display: flex; }
  .m-search__input {
    display: block; width: 100%; max-width: 100%;
    min-height: var(--m-touch, 44px);
    padding: 0 12px 0 36px;
    border-radius: 10px; border: 1px solid var(--line);
    background: var(--bg-card); color: var(--ink);
    font-size: 16px; font-family: inherit;
    box-sizing: border-box;
    -webkit-appearance: none;
  }
  .m-search__input:focus { outline: none; border-color: var(--indigo); }
  /* Intentional horizontal gadget (founder rule: the page never pans sideways;
     only designated rows scroll horizontally, with snap). touch-action here
     re-allows pan-x for gestures that START on the row. */
  .m-chips {
    display: flex; gap: 8px; margin-bottom: 14px;
    max-width: 100%;
    overflow-x: auto; overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain; /* fling stops at the row edge, never pans the page */
    touch-action: pan-x pan-y;
    scroll-snap-type: x proximity;
    scrollbar-width: none;
  }
  .m-chips::-webkit-scrollbar { display: none; }
  .m-chip {
    flex-shrink: 0;
    scroll-snap-align: start;
    min-height: 40px; padding: 0 14px; /* R4: ≥40px touch target */
    border-radius: 16px; border: 1px solid var(--line);
    background: var(--bg-card); color: var(--ink-3);
    font-size: 12.5px; font-weight: 600;
    -webkit-tap-highlight-color: transparent;
  }
  .m-chip--on { background: var(--indigo); border-color: var(--indigo); color: #fff; }
  .m-proj__head { display: flex; align-items: center; gap: 8px; }
  .m-proj__name {
    flex: 1 1 0; min-width: 0;
    font-size: 14.5px; font-weight: 650; color: var(--ink);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .m-proj__risk { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
  .m-proj__meta { display: flex; flex-wrap: wrap; gap: 6px 12px; margin-top: 5px; font-size: 12px; color: var(--ink-4); }
  .m-proj__phase { color: var(--indigo); font-weight: 600; }
  .m-peek__rows { margin-bottom: 4px; }
  .m-peek__row {
    display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
    padding: 9px 0; border-bottom: 1px solid var(--line-soft, var(--line));
    font-size: 13px; color: var(--ink-4);
  }
  .m-peek__row strong { color: var(--ink); font-weight: 600; text-align: right; min-width: 0; overflow-wrap: anywhere; }
  .m-peek__deadline {
    display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
    padding: 7px 0; font-size: 13px;
  }
  .m-peek__deadline-title { color: var(--ink-2); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .m-peek__deadline-date { color: var(--ink-4); flex-shrink: 0; font-size: 12px; }

  /* ── Time (MobileTimePage) ────────────────────────────────────────────────── */
  .m-timer { transition: border-color var(--duration-base) var(--ease-in-out); }
  .m-timer--live   { border-color: var(--indigo); box-shadow: 0 0 0 1px var(--indigo-line); }
  .m-timer--paused { border-color: var(--warn); }
  .m-timer__elapsed {
    font-size: 40px; font-weight: 700; color: var(--ink);
    font-variant-numeric: tabular-nums;
    text-align: center; margin: 6px 0 14px; line-height: 1;
    transition: color var(--duration-base) var(--ease-in-out);
  }
  /* The elapsed readout takes the run-state color so "recording" is unmistakable. */
  .m-timer--live .m-timer__elapsed   { color: var(--indigo); }
  .m-timer--paused .m-timer__elapsed { color: var(--warn); }
  .m-timer__actions { display: flex; gap: 8px; margin-top: 4px; }
  .m-timer__actions .m-btn { flex: 1 1 0; min-width: 0; padding: 0 8px; font-size: 13px; }
  .m-time__today-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
  .m-time__total { font-size: 13px; font-weight: 700; color: var(--ink-2); font-variant-numeric: tabular-nums; }
  .m-entry { display: flex; align-items: flex-start; gap: 10px; padding: 12px 14px; }
  .m-entry__body { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
  .m-entry__proj { font-size: 13.5px; font-weight: 600; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .m-entry__desc { font-size: 12px; color: var(--ink-4); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .m-entry__hours { font-size: 13.5px; font-weight: 700; color: var(--ink-2); flex-shrink: 0; font-variant-numeric: tabular-nums; }
  .m-time__note { font-size: 11.5px; color: var(--ink-5); text-align: center; margin-top: 18px; line-height: 1.5; }

  /* ── Notifications sheet ──────────────────────────────────────────────────── */
  .m-notif {
    display: flex; align-items: flex-start; gap: 10px;
    width: 100%; padding: 11px 2px;
    background: none; border: none; border-bottom: 1px solid var(--line-soft, var(--line));
    text-align: left; -webkit-tap-highlight-color: transparent;
  }
  .m-notif:last-child { border-bottom: none; }
  .m-notif__dot { width: 7px; height: 7px; border-radius: 50%; background: transparent; margin-top: 6px; flex-shrink: 0; }
  .m-notif--unread .m-notif__dot { background: var(--indigo); }
  .m-notif__body { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
  .m-notif__title { font-size: 13.5px; font-weight: 600; color: var(--ink); }
  .m-notif--unread .m-notif__title { font-weight: 700; }
  .m-notif__sub { font-size: 12px; color: var(--ink-4); line-height: 1.45; }

  /* ── Chat — full-height sheet hosting the real CommandBar ───────────────────
     Claude-mobile-app shell (founder Round 5). THEME RULE: the sheet and every
     surface inside it use the same design tokens as the rest of the workspace
     (--bg = Today's page background) — NO hardcoded colors, NO
     prefers-color-scheme here. One tweaks theme everywhere.
     Keyboard: mobile.jsx pins the sheet's height to window.visualViewport, so
     the flex-bottom composer rides directly above the iOS keyboard. */
  .m-chat {
    position: fixed; top: 0; left: 0; right: 0;
    height: 100dvh;          /* JS overrides with the visual-viewport px */
    z-index: calc(var(--m-sheet-z, 9000) + 50);
    display: flex; flex-direction: column;
    background: var(--bg);   /* EXACTLY .m-page's (Today's) background token */
    padding-top: var(--m-safe-top, 0px);
    overflow: hidden;        /* sheet fully covers + clips — nothing behind shows */
  }
  .m-chat__head {
    display: flex; align-items: center; justify-content: space-between;
    height: var(--m-header-h, 52px); flex-shrink: 0;
    padding: 0 var(--m-pad, 16px);
    border-bottom: 1px solid var(--line);
    background: var(--bg);
  }
  .m-chat__title { font-size: 15px; font-weight: 650; color: var(--ink); }
  .m-chat__close {
    display: flex; align-items: center; justify-content: center;
    width: var(--m-touch, 44px); height: var(--m-touch, 44px);
    margin-right: -12px;
    background: none; border: none; color: var(--ink-3); padding: 0;
    -webkit-tap-highlight-color: transparent;
  }
  .m-chat__body { flex: 1 1 0; min-height: 0; display: flex; position: relative; }
  /* Reshape the desktop side panel into the full sheet. Specificity beats the
     bare hide rule below; !important beats the inline width style.
     CRITICAL: the CommandBar mounts with srHidden=true (the mobile shell never
     fires chat:setOpen to "open" it), so it carries .sr-hidden — which in
     styles.css sets opacity:0 + pointer-events:none. Width/display/border are
     re-forced above, but opacity + pointer-events would leak through and make
     the whole chat invisible + untappable ("chat isn't working"). Neutralize
     them here so the reshaped panel is fully visible and interactive. */
  .m-chat .app-chat-panel {
    display: flex !important;
    position: static !important;
    width: 100% !important;
    height: 100% !important;
    max-width: 100% !important;
    flex: 1 1 0;
    border: none !important;
    background: var(--bg);
    overflow: hidden;
    opacity: 1 !important;
    pointer-events: auto !important;
  }
  .m-chat .cmd-resize-handle { display: none !important; }

  /* Slim shell: the sheet header IS the header — the panel's floating head
     (chat name, rename menu) is desktop chrome; hide it. */
  .m-chat .cmd-chat-head { display: none !important; }

  /* Thread: full-height scroller, momentum + containment, no top fade mask
     (it existed to fade under the floating head we just hid). */
  .m-chat .cmd-chat-scroll {
    padding: 14px 14px 10px;
    -webkit-mask-image: none; mask-image: none;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
  }
  /* Claude-style bubbles: user right + tinted, assistant plain left. */
  .m-chat .cmd-chat-row-user { justify-content: flex-end; }
  .m-chat .cmd-chat-bubble { font-size: 15px; line-height: 1.55; }
  .m-chat .cmd-chat-bubble-user {
    background: var(--indigo-soft);
    border-radius: 18px 18px 5px 18px;
    padding: 9px 14px; max-width: 85%; font-size: 15px;
  }

  /* Composer: rounded field pinned at the bottom; attach + mic left, send
     right. ≥16px font = no iOS zoom-on-focus. ~5 lines max, then scrolls. */
  .m-chat .cmd-chat-composer {
    margin: 6px 12px calc(10px + var(--m-safe-bottom, 0px));
    border-radius: 22px;
  }
  .m-chat .cmd-textarea { font-size: 16px; max-height: 130px; }
  .m-chat .cmd-expand-btn { display: none !important; } /* desktop-panel toggle */
  .m-chat .cmd-send, .m-chat .cmd-stop { width: 34px; height: 34px; }
  /* Send activates with content (Claude-style accent). */
  .m-chat .cmd-send:not(:disabled) { background: var(--indigo); color: #fff; }

  /* Empty state: mark + greeting centered in the space ABOVE the composer;
     composer still pinned to the bottom (auto-margins center the hero block
     in the leftover flex space). */
  .m-chat .cmd-general-landing {
    flex: 1 1 auto; min-height: 0;
    padding: 0 12px calc(10px + var(--m-safe-bottom, 0px));
    align-items: stretch;
  }
  .m-chat .cmd-general-landing-inner { max-width: none; height: 100%; }
  .m-chat .cmd-general-landing-icon { margin-top: auto; }
  .m-chat .cmd-general-landing-heading {
    margin-bottom: auto;
    font-size: 22px; font-weight: 600; text-align: center;
    padding-bottom: 56px; /* breathing room above the starter chips */
  }
  .m-chat .cmd-general-landing-composer { border-radius: 22px; }
  .m-chat .cmd-general-landing-composer .cmd-textarea { font-size: 16px; max-height: 130px; }
  /* The CommandBar renders its own desktop starter chips inside the landing;
     mobile draws its own floating .m-chat__chips above the composer, so the
     desktop set would duplicate below it. Hide the desktop set on mobile. */
  .m-chat .cmd-starter-chips { display: none !important; }

  /* Starter chips (rendered by mobile.jsx, empty state only) — float just
     above the resting composer. */
  .m-chat__chips {
    position: absolute; left: 14px; right: 14px;
    bottom: calc(118px + var(--m-safe-bottom, 0px));
    display: flex; flex-wrap: wrap; gap: 8px;
    justify-content: center;
    pointer-events: none; /* gaps stay click-through to the textarea below */
  }
  .m-chat__chip {
    pointer-events: auto;
    max-width: 100%;
    min-height: 36px; padding: 7px 14px;
    border-radius: 18px;
    background: var(--bg-card); border: 1px solid var(--line);
    font-size: 13px; font-weight: 550; color: var(--ink-2);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    -webkit-tap-highlight-color: transparent;
  }

  /* ── App-shell reshaping for routes still rendered under AppShell ─────────── */
  /* (Command Center, Settings, Members, Deadlines, … reached via the More
     sheet. Their pages are Round-2/3 adaptation targets; the chrome + these
     rules keep them navigable: vertically scrollable, horizontally clamped
     (founder rule: stack don't shrink — full adaptation later, scroll/clamp
     mandatory now). */
  html.aecos-mobile-preview .app-root > .app-chat-panel { display: none !important; }
  html.aecos-mobile-preview .topbar { display: none !important; }
  html.aecos-mobile-preview .app-root,
  html.aecos-mobile-preview .app-right { max-width: 100%; min-width: 0; }
  html.aecos-mobile-preview .page {
    padding-top: calc(var(--m-header-h, 52px) + var(--m-safe-top, 0px) + 10px);
    max-width: 100vw;
    min-width: 0;
    overflow-y: auto;
    overflow-x: hidden;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
    touch-action: pan-y pinch-zoom;
  }
  /* Bind desktop page content to the viewport. Direct children clamp hard;
     fixed-width grids stack to one column instead of shrinking side-by-side.
     minmax(0,1fr) — a bare 1fr track can't shrink below its item's
     min-content (a wide table inside a card blew the track to 684px at 375px
     wide, verified in QA); min-width:0 on items for the same reason. */
  html.aecos-mobile-preview .page > * { max-width: 100%; min-width: 0; }
  /* !important: some pages set gridTemplateColumns INLINE (e.g. pages-2
     Deadlines "2fr 1fr"), which otherwise beats any stylesheet rule and
     squeezes cards to ~100px. */
  html.aecos-mobile-preview .page .grid-2,
  html.aecos-mobile-preview .page .grid-3 { grid-template-columns: minmax(0, 1fr) !important; }
  html.aecos-mobile-preview .page .grid-metrics { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
  html.aecos-mobile-preview .page .grid-2 > *,
  html.aecos-mobile-preview .page .grid-3 > *,
  html.aecos-mobile-preview .page .grid-metrics > * { min-width: 0; max-width: 100%; }
  html.aecos-mobile-preview .page .card { min-width: 0; max-width: 100%; }
  /* P0: invoice editor is a form|preview split (pages-2.jsx) that never
     collapses — at 390px the form column crushed to ~56px (unusable). Stack
     the split vertically (form full-width on top, live preview below) and let
     the whole thing scroll. The editor renders OUTSIDE .page, so these aren't
     .page-scoped. */
  html.aecos-mobile-preview .invoice-split {
    /* !important: the container sets overflow:hidden INLINE, which beats a bare
       stylesheet rule and would clip the now-stacked form+preview. */
    flex-direction: column !important; overflow-y: auto !important; overflow-x: hidden !important;
    -webkit-overflow-scrolling: touch;
  }
  html.aecos-mobile-preview .invoice-split > * {
    flex: 0 0 auto !important; width: 100%; min-width: 0;
    overflow-y: visible !important;   /* defeat the form column's nested scroll */
  }
  /* The line-item rows are a 9-column inline grid ("20px 28px 1fr 1.6fr 0.7fr
     1fr 1fr 60px 56px"); even full-width it needs ~600px, so scroll it
     horizontally inside its card rather than crush the fr columns. */
  html.aecos-mobile-preview .inv-lines-card {
    overflow-x: auto; -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain;
  }
  html.aecos-mobile-preview .inv-lines-grid { min-width: 600px; }
  /* Settings: 2-col form grid → single column; profile hero row wraps
     (founder rule #2: stack, don't shrink — these were spilling past 375px). */
  html.aecos-mobile-preview .page .ct-fields { grid-template-columns: minmax(0, 1fr); }
  html.aecos-mobile-preview .page .ct-hero { flex-wrap: wrap; }
  html.aecos-mobile-preview .page .ct-linked-row { flex-wrap: wrap; }
  html.aecos-mobile-preview .page .ct-linked-val { min-width: 0; overflow-wrap: anywhere; }
  /* In-page tab strips (.tabs — Deadlines, project detail, …) overflow at
     phone widths: designated horizontal-swipe gadget (founder rule #3). */
  html.aecos-mobile-preview .page .tabs {
    max-width: 100%;
    flex-wrap: nowrap;
    overflow-x: auto; overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
    touch-action: pan-x pan-y;
    scrollbar-width: none;
  }
  html.aecos-mobile-preview .page .tabs::-webkit-scrollbar { display: none; }
  html.aecos-mobile-preview .page .tabs > * { flex-shrink: 0; }
  /* Wide data tables become designated horizontal-scroll gadgets (the page
     itself still never pans — gestures starting on the table pan the table). */
  html.aecos-mobile-preview .page table {
    display: block;
    max-width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
    touch-action: pan-x pan-y;
  }
  /* ── Round-3 route sweep fixes (geometry-audited at 320/375/430) ──────────
     Each block fixes a measured clipped-past-viewport offender on a route
     reachable from the More sheet. Pattern: stack/wrap, never shrink. */

  /* Project detail → Phases tab: .phase-card-head row (chevron + info +
     160px bar + actions) clipped its Edit/Delete buttons at ≤375px. */
  html.aecos-mobile-preview .page .phase-card-head { flex-wrap: wrap; }
  html.aecos-mobile-preview .page .phase-bar-wrap { flex: 1 1 100%; }
  html.aecos-mobile-preview .page .phase-card-actions { flex-wrap: wrap; width: 100%; justify-content: flex-start; }

  /* Reports: report sheet paddings + header meta + body rows (buttons sat
     at x≈419 inside non-wrapping flex rows). */
  html.aecos-mobile-preview .page .report-head,
  html.aecos-mobile-preview .page .report-body { padding: 16px var(--m-pad, 16px); }
  html.aecos-mobile-preview .page .report-head *,
  html.aecos-mobile-preview .page .report-body * { min-width: 0; overflow-wrap: anywhere; }
  html.aecos-mobile-preview .page .report-body div { flex-wrap: wrap; }

  /* Reports pane: the single-column grid used a bare 1fr track, which can't
     shrink below its content's min-content width — content blew past 320px. */
  html.aecos-mobile-preview .page .report-pane { grid-template-columns: minmax(0, 1fr) !important; }

  /* Offices: the per-card 4-across stats grid (inline style) has a ~350px
     min-content floor — stack to 2×2 (footer 2-col gets minmax too). */
  html.aecos-mobile-preview .page .office-card-link > div[style*="grid"] {
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
  }

  /* Recent Activity (reuses the RFI filter toolbar): selects row clipped
     the search input at 320px. */
  html.aecos-mobile-preview .page .rfi-filter-row,
  html.aecos-mobile-preview .page .rfi-filter-selects { flex-wrap: wrap; max-width: 100%; }
  html.aecos-mobile-preview .page .rfi-search-wrap { min-width: 0; flex: 1 1 100%; }

  /* Members: stats row, toolbar + 220px search, and the table-shaped list
     rows all clipped. Stack the toolbar; let rows wrap (invite rows keep
     this wrap fallback; member rows get the R4 card grid below). */
  html.aecos-mobile-preview .page .members-stats { flex-wrap: wrap; }
  html.aecos-mobile-preview .page .members-stat-card { flex: 1 1 42%; min-width: 0; }
  html.aecos-mobile-preview .page .members-toolbar { flex-wrap: wrap; }
  html.aecos-mobile-preview .page .members-filters { flex-wrap: wrap; }
  html.aecos-mobile-preview .page .members-search { min-width: 0; flex: 1 1 100%; }
  html.aecos-mobile-preview .page .members-list-head { display: none; }
  html.aecos-mobile-preview .page .members-list-row { flex-wrap: wrap; row-gap: 6px; }
  html.aecos-mobile-preview .page .members-list-row > * { min-width: 0; max-width: 100%; }

  /* ── Round-4 visual polish (headless-screenshot audited at 320/375/430) ── */

  /* Members — mobile card redesign. The desktop member row is a 9-cell flex
     table line (checkbox · avatar · name/email · office · role · status ·
     last-active · joined · remove); R3's wrap made it usable but ugly
     (dangling "—" cells, orphaned Remove). Card grid:
       avatar | name + email      | role badge
              | office            | status
     Bulk select, last-active, joined and Remove stay on desktop / in the
     member panel (tapping the row opens it). :has(> .members-select-cell)
     scopes to MEMBER rows only — pending-invite rows reuse the class with a
     different cell list and keep the wrap fallback above. */
  html.aecos-mobile-preview .page .members-list-row:has(> .members-select-cell) {
    display: grid !important;
    grid-template-columns: 46px minmax(0, 1fr) auto;
    align-items: center;
    row-gap: 3px; column-gap: 0;
    padding: 12px 14px;
  }
  html.aecos-mobile-preview .page .members-list-row:has(> .members-select-cell) > .members-select-cell { display: none; }
  html.aecos-mobile-preview .page .members-list-row:has(> .members-select-cell) > :nth-child(2) { grid-column: 1; grid-row: 1 / span 2; }
  html.aecos-mobile-preview .page .members-list-row:has(> .members-select-cell) > :nth-child(3) { grid-column: 2; grid-row: 1; min-width: 0; }
  html.aecos-mobile-preview .page .members-list-row:has(> .members-select-cell) > :nth-child(4) {
    grid-column: 2; grid-row: 2;
    font-size: 11.5px !important; color: var(--ink-4) !important;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  html.aecos-mobile-preview .page .members-list-row:has(> .members-select-cell) > :nth-child(5) { grid-column: 3; grid-row: 1; justify-self: end; }
  html.aecos-mobile-preview .page .members-list-row:has(> .members-select-cell) > :nth-child(6) { grid-column: 3; grid-row: 2; justify-self: end; }
  /* Everything past status (last-active · joined · remove) lives in the
     member panel on mobile; tap the row to open it. !important: the Remove
     cell carries an inline display:flex. */
  html.aecos-mobile-preview .page .members-list-row:has(> .members-select-cell) > :nth-child(n+7) { display: none !important; }
  /* Invite form: desktop 4-column grid (1fr 1fr 140px 140px inline style). */
  html.aecos-mobile-preview .page div[style*="1fr 1fr 140px"] { grid-template-columns: minmax(0, 1fr) !important; }

  /* Settings — R6 two-level master-detail (MobileSettingsShell in mobile.jsx),
     replacing the R4 <select>. The page's own .settings-mobile-select stays in
     the DOM (the shell drives it programmatically to switch sections) but is
     never shown; the side list stays hidden. Level 1 (html.m-settings--list):
     the shell's full-width section list covers the page — the underlying grid
     + page head are hidden. Level 2: the section card full-width under a fixed
     back bar. */
  html.aecos-mobile-preview .page .settings-grid { display: block; }
  html.aecos-mobile-preview .page .settings-side { display: none; }
  html.aecos-mobile-preview .page .settings-mobile-select { display: none; }
  html.aecos-mobile-preview.m-settings--list .page .settings-grid,
  html.aecos-mobile-preview.m-settings--list .page .page-head { display: none; }
  /* Detail level: clear the fixed back bar (44px) below the fixed header. */
  html.aecos-mobile-preview.m-settings:not(.m-settings--list) .page {
    padding-top: calc(var(--m-header-h, 52px) + var(--m-safe-top, 0px) + 54px);
  }
  html.aecos-mobile-preview.m-settings:not(.m-settings--list) .page .page-head { display: none; }
  .m-set {
    position: fixed; left: 0; right: 0;
    top: calc(var(--m-header-h, 52px) + var(--m-safe-top, 0px));
    bottom: calc(var(--m-tabbar-h, 64px) + var(--m-safe-bottom, 0px));
    overflow-y: auto; -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
    background: var(--bg);
    padding: 12px var(--m-pad, 16px) 24px;
    z-index: 800;
  }
  .m-set__title {
    font-size: 19px; font-weight: 700; letter-spacing: -0.02em;
    color: var(--ink); margin: 4px 2px 10px;
  }
  .m-set__row {
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    width: 100%; max-width: 100%;
    min-height: var(--m-touch, 44px);
    padding: 12px 2px;
    background: none; border: none;
    border-bottom: 1px solid var(--line-soft);
    font-size: 15px; color: var(--ink-2); font-family: inherit;
    text-align: left;
    -webkit-tap-highlight-color: transparent;
  }
  .m-set__row-label { min-width: 0; overflow-wrap: anywhere; }
  .m-set__chev { display: flex; color: var(--ink-5); flex-shrink: 0; }
  .m-set__backbar {
    position: fixed; left: 0; right: 0;
    top: calc(var(--m-header-h, 52px) + var(--m-safe-top, 0px));
    height: 44px;
    display: flex; align-items: center; gap: 8px;
    padding: 0 var(--m-pad, 16px);
    background: var(--bg-card);
    border-bottom: 1px solid var(--line);
    z-index: 800;
  }
  .m-set__back {
    display: flex; align-items: center; gap: 4px;
    min-height: var(--m-touch, 44px);
    padding: 0;
    background: none; border: none;
    font-size: 14.5px; font-weight: 600; color: var(--indigo); font-family: inherit;
    -webkit-tap-highlight-color: transparent;
  }
  .m-set__back-chev { display: flex; transform: rotate(180deg); }
  .m-set__cur {
    font-size: 14.5px; font-weight: 650; color: var(--ink);
    min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }

  /* Office detail: "Not configured" (Billing rate) blew out of its half-width
     stat card — long non-numeric NumberStat values wrap between words instead
     of clipping (break-word, NOT anywhere — "795h" must never split). */
  html.aecos-mobile-preview .page .numstat-value { overflow-wrap: break-word; }
  html.aecos-mobile-preview .page .grid-metrics .numstat-value { font-size: 24px; line-height: 1.15; }

  /* Studio Review: "Press ? for keyboard shortcuts" — meaningless on touch,
     and it rendered halfway under the tab bar. */
  html.aecos-mobile-preview .sr-shortcut-hint { display: none !important; }

  /* In-page tab strips: right edge-fade as a visible "more tabs" affordance
     (founder rule #3 — overflowing strips need explicit affordance). */
  html.aecos-mobile-preview .page .tabs {
    -webkit-mask-image: linear-gradient(to right, black calc(100% - 28px), transparent 100%);
    mask-image: linear-gradient(to right, black calc(100% - 28px), transparent 100%);
  }

  /* Offices: card head row (name block | clock + sparkline + arrow) clipped
     the clock/pill/sparkline at every phone width. */
  html.aecos-mobile-preview .page .office-head { flex-wrap: wrap; row-gap: 10px; }
  html.aecos-mobile-preview .page .office-head > * { min-width: 0; max-width: 100%; }
  html.aecos-mobile-preview .page .office-clock { white-space: normal; align-items: flex-start; }

  /* Settings: MFA callout button + linked-account key strings. */
  html.aecos-mobile-preview .page .mfa-callout { flex-wrap: wrap; }
  html.aecos-mobile-preview .page .ct-linked-key { min-width: 0; overflow-wrap: anywhere; }

  /* Media + canvases (charts) never overflow the viewport.
     (Studio Review's sheet <svg> is exempt by construction: its width/height
     are INLINE styles, which beat this non-!important rule — zoom keeps
     working. Verified live; do not add !important here.) */
  html.aecos-mobile-preview .page img,
  html.aecos-mobile-preview .page svg,
  html.aecos-mobile-preview .page canvas,
  html.aecos-mobile-preview .page video,
  html.aecos-mobile-preview .page iframe { max-width: 100%; height: auto; }

  /* ── MobileGantt — stacked phase list (default) + timeline gadget ──────────
     Round 3 founder brief: the Gantt is REDESIGNED for phones, not shrunk.
     .m-ph = one card per top-level phase; .m-gtl = the deliberate full-bleed
     horizontally-scrolling timeline strip (the page never pans — only this
     gadget scrolls sideways, with momentum + a visible swipe affordance). */
  .m-gantt { width: 100%; max-width: 100%; margin-bottom: 18px; }
  .m-gantt__top {
    display: flex; align-items: center; justify-content: space-between;
    gap: 6px 10px; margin-bottom: 10px;
    flex-wrap: wrap; /* R4: Phases · Timeline · + Add overflowed 320px */
  }
  .m-gantt__toggle { display: flex; gap: 6px; flex-shrink: 0; flex-wrap: wrap; }
  @media (max-width: 380px) {
    .m-gantt__toggle .m-chip { padding: 0 11px; font-size: 12px; }
  }
  .m-gantt__proj { margin-bottom: 4px; }
  .m-gantt__proj-head {
    display: flex; align-items: center; gap: 8px;
    width: 100%; min-height: var(--m-touch, 44px);
    padding: 8px 2px;
    background: none; border: none; border-bottom: 1px solid var(--line-soft, var(--line));
    text-align: left; -webkit-tap-highlight-color: transparent;
  }
  .m-gantt__proj-chev { display: flex; color: var(--ink-5); transition: transform var(--duration-fast) var(--ease-in-out); }
  .m-gantt__proj-chev--open { transform: rotate(90deg); }
  .m-gantt__proj-name {
    flex: 1 1 0; min-width: 0;
    font-size: 14px; font-weight: 650; color: var(--ink);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .m-gantt__proj-count { font-size: 11.5px; color: var(--ink-4); flex-shrink: 0; }
  .m-gantt__ro { font-size: 11.5px; color: var(--ink-5); margin-top: 8px; line-height: 1.5; }
  .m-gantt__loose { margin-top: 2px; }
  /* R6 master-detail: project cards on the master level… */
  .m-gantt__pcard {
    display: flex; align-items: center; gap: 10px;
    width: 100%; max-width: 100%;
    min-height: var(--m-touch, 44px);
    margin-bottom: 8px; padding: 12px 14px;
    background: var(--bg-card); border: 1px solid var(--line);
    border-radius: var(--m-radius, 12px);
    text-align: left; font-family: inherit;
    -webkit-tap-highlight-color: transparent;
  }
  .m-gantt__pcard-body { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
  .m-gantt__pcard .m-gantt__proj-name { flex: none; }
  .m-gantt__pcard-chev { display: flex; color: var(--ink-5); flex-shrink: 0; }
  /* …and the back chevron on the detail level. */
  .m-gantt__back {
    display: flex; align-items: center; gap: 5px;
    min-height: var(--m-touch, 44px); min-width: 0; flex: 1 1 0;
    padding: 0;
    background: none; border: none; font-family: inherit;
    text-align: left; -webkit-tap-highlight-color: transparent;
  }
  .m-gantt__back-chev { display: flex; color: var(--indigo); transform: rotate(180deg); flex-shrink: 0; }
  .m-gantt__back-name {
    min-width: 0;
    font-size: 14px; font-weight: 650; color: var(--ink);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }

  /* Phase card */
  .m-ph {
    background: var(--bg-card);
    border: 1px solid var(--line);
    border-left: 3px solid var(--indigo);
    border-radius: var(--m-radius, 12px);
    padding: 12px 14px;
    margin-bottom: var(--m-gap, 12px);
    max-width: 100%;
  }
  .m-ph__head {
    display: flex; align-items: center; gap: 8px;
    width: 100%; padding: 0; background: none; border: none;
    text-align: left; -webkit-tap-highlight-color: transparent;
  }
  .m-ph__name {
    flex: 1 1 0; min-width: 0;
    font-size: 14.5px; font-weight: 650; color: var(--ink);
    overflow-wrap: anywhere;
  }
  .m-ph__chip {
    flex-shrink: 0;
    font-size: 10.5px; font-weight: 700; letter-spacing: 0.02em;
    padding: 3px 9px; border-radius: 10px;
  }
  .m-ph__dates {
    display: flex; align-items: center; gap: 6px;
    font-size: 12px; color: var(--ink-4); margin-top: 6px;
  }
  .m-ph__fee { margin-left: auto; font-weight: 650; color: var(--ink-2); font-variant-numeric: tabular-nums; }
  .m-ph__prog { display: flex; align-items: center; gap: 10px; margin-top: 9px; }
  .m-ph__bar {
    flex: 1 1 0; min-width: 0; height: 6px;
    border-radius: 3px; background: var(--bg-elev);
    overflow: hidden;
  }
  .m-ph__fill { height: 100%; border-radius: 3px; }
  .m-ph__pct { flex-shrink: 0; font-size: 11px; font-variant-numeric: tabular-nums; }
  .m-ph__foot { display: flex; align-items: center; gap: 12px; margin-top: 6px; }
  .m-ph__more, .m-ph__edit {
    background: none; border: none;
    padding: 9px 0; min-height: 38px; /* roomier tap zone for the inline actions */
    display: inline-flex; align-items: center;
    font-size: 12px; font-weight: 600; color: var(--indigo);
    -webkit-tap-highlight-color: transparent;
  }
  .m-ph__edit { margin-left: auto; }
  .m-ph__detail { margin-top: 4px; border-top: 1px solid var(--line-soft, var(--line)); padding-top: 8px; }
  .m-ph__note { font-size: 12px; color: var(--ink-3); line-height: 1.5; margin-bottom: 8px; }
  .m-ph__sub {
    display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
    padding: 6px 0 6px 10px; border-left: 2px solid var(--line);
    margin-bottom: 2px;
  }
  .m-ph__sub-name { font-size: 12.5px; font-weight: 600; color: var(--ink-2); min-width: 0; overflow-wrap: anywhere; }
  .m-ph__sub-meta { font-size: 11px; color: var(--ink-4); flex-shrink: 0; text-align: right; }
  .m-ph__ms { display: flex; align-items: center; gap: 8px; padding: 6px 0; }
  .m-ph__ms-d {
    width: 8px; height: 8px; flex-shrink: 0;
    background: var(--indigo); transform: rotate(45deg);
  }
  .m-ph__ms--done .m-ph__ms-d { background: var(--ok); }
  .m-ph__ms-l { flex: 1 1 0; min-width: 0; font-size: 12.5px; color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .m-ph__ms--done .m-ph__ms-l { text-decoration: line-through; color: var(--ink-4); }
  .m-ph__ms-date { flex-shrink: 0; font-size: 11px; color: var(--ink-4); font-variant-numeric: tabular-nums; }

  /* Phase edit sheet — stack PhaseForm's .field-row flex rows vertically
     (founder rule #2: stack, don't shrink). Scoped to the sheet only. */
  .m-phform .field-row { flex-wrap: wrap; }
  .m-phform .phase-form-title { display: none; } /* the sheet already says "Edit phase" */
  .m-phform .field-group { flex: 1 1 100% !important; min-width: 0; }
  .m-phform .field-input { min-height: 40px; font-size: 16px; /* no iOS zoom */ }
  .m-phform .phase-form { max-height: none !important; overflow: visible !important; padding-right: 0 !important; }

  /* Timeline gadget — full-bleed within the page gutter */
  .m-gtl {
    margin: 0 calc(-1 * var(--m-pad, 16px));
    max-width: none;
  }
  .m-gtl__hint {
    font-size: 11px; font-weight: 600; color: var(--ink-4);
    padding: 0 var(--m-pad, 16px) 6px;
  }
  .m-gtl__scroll {
    overflow-x: auto; overflow-y: hidden;
    -webkit-overflow-scrolling: touch;       /* momentum */
    overscroll-behavior-x: contain;          /* fling never pans the page */
    touch-action: pan-x pan-y;
    background: var(--bg-card);
    border-top: 1px solid var(--line);
    border-bottom: 1px solid var(--line);
    /* edge fade = visible "there's more" affordance */
    -webkit-mask-image: linear-gradient(to right, transparent 0, black 12px, black calc(100% - 12px), transparent 100%);
    mask-image: linear-gradient(to right, transparent 0, black 12px, black calc(100% - 12px), transparent 100%);
  }
  .m-gtl__scroll::-webkit-scrollbar { height: 4px; }
  .m-gtl__scroll::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: 2px; }
  .m-gtl__inner { position: relative; padding: 26px 0 10px; min-height: 60px; }
  .m-gtl__months { position: absolute; top: 0; left: 0; right: 0; height: 22px; border-bottom: 1px solid var(--line-soft, var(--line)); }
  .m-gtl__month {
    position: absolute; top: 0; height: 22px;
    display: flex; align-items: center;
    padding-left: 6px;
    font-size: 10px; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase;
    color: var(--ink-5);
    border-left: 1px solid var(--line-soft, var(--line));
    overflow: hidden; white-space: nowrap;
  }
  .m-gtl__row { position: relative; height: 34px; }
  .m-gtl__bar {
    position: absolute; top: 5px; height: 24px;
    border: 1px solid; border-radius: 6px;
    overflow: hidden;
  }
  .m-gtl__fill { position: absolute; left: 0; top: 0; bottom: 0; opacity: 0.28; }
  .m-gtl__bar-label {
    position: absolute; left: 7px; top: 50%; transform: translateY(-50%);
    font-size: 10.5px; font-weight: 700; white-space: nowrap;
    max-width: calc(100% - 12px); overflow: hidden; text-overflow: ellipsis;
  }
  .m-gtl__ms-row { position: relative; height: 30px; }
  .m-gtl__ms { position: absolute; top: 4px; display: flex; align-items: center; gap: 5px; transform: translateX(-4px); }
  .m-gtl__ms-d { width: 8px; height: 8px; background: var(--indigo); transform: rotate(45deg); flex-shrink: 0; }
  .m-gtl__ms--done .m-gtl__ms-d { background: var(--ok); }
  .m-gtl__ms-l { font-size: 10px; color: var(--ink-4); white-space: nowrap; max-width: 110px; overflow: hidden; text-overflow: ellipsis; }
  .m-gtl__today { position: absolute; top: 22px; bottom: 0; width: 2px; background: var(--bad); opacity: 0.65; }

  /* ── Studio Review — minimum viable mobile (view + browse + chat) ──────────
     Founder brief: view the drawing (pinch-zoom + pan — the ONE surface where
     canvas panning is intentional), browse markups, read comments, chat with
     the Specialist. Authoring defers to desktop: props dock, right tool
     strip, inline props toolbar and the desktop menu headings are hidden;
     the left rail stays (compact icon affordance) and every side panel
     becomes a bottom sheet that leaves the mobile tab bar reachable. */

  /* SR page frame: full-bleed between the mobile header + tab bar. Out-
     specifies the generic .page padding rule via :has(). */
  html.aecos-mobile-preview .page:has(.studio-review-page) {
    padding: calc(var(--m-header-h, 52px) + var(--m-safe-top, 0px)) 0
             calc(var(--m-tabbar-h, 64px) + var(--m-safe-bottom, 0px));
    overflow: hidden;
  }

  /* SR dashboard (list/index) toolbar: the search field shares a flex row with
     the Active/Archived/Trash segment + view toggle and got crushed to ~25px on
     phones (unreadable). Give it a full-width row of its own — the toolbar
     already flex-wraps, so the segment + view toggle drop to the next line. */
  html.aecos-mobile-preview .sr-dash-toolbar .sr-dash-search {
    flex: 1 1 100%;
    min-width: 0;
  }

  /* Menu bar: desktop menu headings are authoring surface — hide. Keep the
     logo + session crumb + Sessions-back + fullscreen buttons. */
  html.aecos-mobile-preview .sr-menu-heading { display: none; }
  html.aecos-mobile-preview .sr-menu-bar-right { min-width: 0; flex: 0 1 auto; overflow: hidden; }
  html.aecos-mobile-preview .sr-crumb-pill { min-width: 0; flex: 0 1 auto; overflow: hidden; }
  html.aecos-mobile-preview .sr-crumb-pill strong {
    max-width: 12ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  html.aecos-mobile-preview .sr-menu-action-btn { flex-shrink: 0; }
  @media (max-width: 380px) {
    /* SE-class: project crumb gives way to the action buttons */
    html.aecos-mobile-preview .sr-crumb-pill { display: none; }
    html.aecos-mobile-preview .sr-menu-action-btn .sr-menu-action-label { display: none; }
  }

  /* Authoring chrome off */
  html.aecos-mobile-preview .sr-props-dock,
  html.aecos-mobile-preview .sr-right-tool-strip,
  html.aecos-mobile-preview .sr-props-toolbar-inline { display: none !important; }

  /* Left rail: keep (compact, thumb-reachable). Bigger touch targets, no
     hover tooltips (no hover on touch). */
  html.aecos-mobile-preview .sr-rail-btn { width: 40px; height: 42px; }
  html.aecos-mobile-preview .sr-rail-tip { display: none; }

  /* Side panels become bottom sheets that stop ABOVE the mobile tab bar so
     navigation is never trapped. All three panel hosts get the treatment. */
  html.aecos-mobile-preview .sr-left-panel,
  html.aecos-mobile-preview .sr-code-check-panel,
  html.aecos-mobile-preview .sr-right-panel-slide {
    position: fixed; left: 0; right: 0; top: auto;
    bottom: calc(var(--m-tabbar-h, 64px) + var(--m-safe-bottom, 0px));
    width: 100%; max-width: 100%;
    height: min(62dvh, 480px);
    z-index: 8400; /* below the m-tabbar (8500) — tabs stay tappable */
    border: 1px solid var(--line); border-bottom: none;
    border-radius: 14px 14px 0 0;
    box-shadow: 0 -14px 40px rgba(0, 0, 0, 0.22);
  }
  /* Their close buttons are small desktop targets — enlarge. */
  html.aecos-mobile-preview .sr-lp-close,
  html.aecos-mobile-preview .sr-props-dock-collapse-btn { width: 30px; height: 30px; }
  html.aecos-mobile-preview .sr-lp-head { height: 38px; }

  /* Canvas: native one-finger pan via the scroll container; two-finger pinch
     goes to the viewer's JS pinch-zoom (touch-action pan-x pan-y stops the
     browser from page-zooming instead). The deliberate exception to the
     "page never pans sideways" rule. */
  html.aecos-mobile-preview .sr-viewer-scroll {
    touch-action: pan-x pan-y;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
  }

  /* Bottom status/nav bar: designated horizontal gadget (page nav, zoom,
     markup-list toggle all stay reachable). */
  html.aecos-mobile-preview .sr-nav-bar {
    overflow-x: auto; overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
    touch-action: pan-x;
    scrollbar-width: none;
  }
  html.aecos-mobile-preview .sr-nav-bar::-webkit-scrollbar { display: none; }
  html.aecos-mobile-preview .sr-nav-bar > * { flex-shrink: 0; }
  html.aecos-mobile-preview .sr-nav-file-lbl { max-width: 120px; }

  /* Bottom panel (markups list): never eat the whole canvas. */
  html.aecos-mobile-preview .sr-btm-panel { max-height: 38dvh; }

  /* Status strip: cursor-coords + Demo/Live tag clipped at 320px — same
     horizontal-gadget treatment as the nav bar. */
  html.aecos-mobile-preview .sr-status-bar {
    overflow-x: auto; overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
    touch-action: pan-x;
    scrollbar-width: none;
  }
  html.aecos-mobile-preview .sr-status-bar::-webkit-scrollbar { display: none; }
  html.aecos-mobile-preview .sr-status-bar > * { flex-shrink: 0; }
  html.aecos-mobile-preview .sr-status-msg { flex: 1 0 auto; max-width: 60vw; }

  /* Modals: phone-safe (some are 520-960px wide on desktop). */
  html.aecos-mobile-preview .sr-modal-overlay { padding: 10px; }
  html.aecos-mobile-preview .sr-modal,
  html.aecos-mobile-preview .sr-modal-lg,
  html.aecos-mobile-preview .sr-modal-xl {
    max-width: 100%; max-height: min(86dvh, 640px);
    /* clamp WITHOUT scroll silently clipped tall modals (Session settings,
       Share, Specialist knowledge entry) below the fold. */
    overflow-y: auto; -webkit-overflow-scrolling: touch; overscroll-behavior: contain;
  }

  /* SR dashboard (session list) — stack, don't shrink. */
  html.aecos-mobile-preview .sr-dashboard { padding: var(--m-pad, 16px); }
  html.aecos-mobile-preview .sr-metric-row { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  html.aecos-mobile-preview .sr-section-row,
  html.aecos-mobile-preview .sr-section-row-3 { grid-template-columns: minmax(0, 1fr) !important; }
  html.aecos-mobile-preview .sr-dash-toolbar { flex-wrap: wrap; }

  /* ── Access-denied notice (financial clearance) ───────────────────────────── */
  .m-denied {
    display: flex; flex-direction: column; align-items: center; text-align: center;
    gap: 8px; padding: 40px 20px; margin-top: 8px;
  }
  .m-denied__icon { color: var(--ink-5); display: flex; }
  .m-denied__title { font-size: 16px; font-weight: 700; color: var(--ink); }
  .m-denied__body { font-size: 13px; color: var(--ink-4); line-height: 1.55; max-width: 300px; }

  /* ── Bookkeeping (MobileBookkeepingPage) ──────────────────────────────────── */
  .m-bk__head {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    margin: 4px 0 12px;
  }
  .m-bk__count { display: flex; align-items: baseline; gap: 7px; min-width: 0; }
  .m-bk__count-n { font-size: 26px; font-weight: 700; color: var(--ink); line-height: 1; font-variant-numeric: tabular-nums; }
  .m-bk__count-l { font-size: 12.5px; color: var(--ink-4); }
  .m-bk__postall { min-height: 40px; padding: 0 14px; flex-shrink: 0; }
  /* Transaction card */
  .m-txn { padding: 13px 15px; }
  .m-txn__top { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
  .m-txn__merchant {
    flex: 1 1 0; min-width: 0; font-size: 14.5px; font-weight: 650; color: var(--ink);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .m-txn__amount { flex-shrink: 0; font-size: 15px; font-weight: 700; color: var(--ink-2); font-variant-numeric: tabular-nums; }
  .m-txn__amount--in { color: var(--ok); }
  .m-txn__meta { font-size: 12px; color: var(--ink-4); margin-top: 3px; font-variant-numeric: tabular-nums; }
  .m-txn__cat {
    display: flex; align-items: center; gap: 7px; width: 100%;
    min-height: var(--m-touch, 44px); margin-top: 10px; padding: 0 12px;
    border-radius: 10px; border: 1px solid var(--line); background: var(--bg-elev);
    text-align: left; -webkit-tap-highlight-color: transparent;
    transition: background-color var(--duration-fast) var(--ease-in-out), border-color var(--duration-fast) var(--ease-in-out);
  }
  .m-txn__cat:active { background: var(--bg-sunk, var(--bg-card)); border-color: var(--line-strong); }
  .m-txn__cat-icon { color: var(--indigo); display: flex; flex-shrink: 0; }
  .m-txn__cat-name {
    flex: 1 1 0; min-width: 0; font-size: 13.5px; font-weight: 600; color: var(--ink);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .m-txn__cat-name--empty { color: var(--warn); }
  .m-txn__cat-chev { color: var(--ink-5); flex-shrink: 0; display: flex; }
  .m-txn__actions { margin-top: 10px; }
  .m-txn__approve { width: 100%; min-height: var(--m-touch, 44px); }
  /* Category picker sheet */
  .m-catpick__group { margin-bottom: 6px; }
  .m-catpick__group-label {
    font-size: 11px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
    color: var(--ink-4); margin: 14px 0 4px;
  }
  .m-catpick__opt {
    display: flex; align-items: center; gap: 10px; width: 100%;
    min-height: var(--m-touch, 44px); padding: 8px 4px;
    background: none; border: none; border-bottom: 1px solid var(--line-soft, var(--line));
    text-align: left; -webkit-tap-highlight-color: transparent;
    transition: background-color var(--duration-fast) var(--ease-in-out);
  }
  .m-catpick__opt:active { background: var(--bg-sunk, var(--bg-elev)); }
  .m-catpick__opt-name { flex: 1 1 0; min-width: 0; font-size: 14px; color: var(--ink); overflow-wrap: anywhere; }
  .m-catpick__opt--on .m-catpick__opt-name { font-weight: 700; color: var(--indigo); }
  .m-catpick__opt-check { color: var(--indigo); display: flex; flex-shrink: 0; }
  /* Toast */
  .m-bk__toast {
    position: fixed; left: 50%; transform: translateX(-50%);
    bottom: calc(var(--m-tabbar-h, 64px) + var(--m-safe-bottom, 0px) + 14px);
    z-index: var(--m-sheet-z, 9000);
    max-width: calc(100% - 32px);
    padding: 10px 16px; border-radius: 22px;
    background: var(--ink); color: var(--bg);
    font-size: 13px; font-weight: 600; text-align: center;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.22);
  }
  /* Statements */
  .m-stmt__section {
    font-size: 11px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
    color: var(--ink-4); margin: 12px 0 4px;
  }
  .m-stmt__section:first-child { margin-top: 0; }
  .m-stmt__row {
    display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
    padding: 8px 0; border-bottom: 1px solid var(--line-soft, var(--line));
    font-size: 13.5px;
  }
  .m-stmt__row--total { border-top: 1px solid var(--line-strong); border-bottom: none; margin-top: 2px; padding-top: 9px; }
  .m-stmt__label { color: var(--ink-3); min-width: 0; overflow-wrap: anywhere; }
  .m-stmt__row--total .m-stmt__label { color: var(--ink); font-weight: 700; }
  .m-stmt__val { flex-shrink: 0; font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }
  .m-stmt__row--total .m-stmt__val { font-weight: 700; }
  .m-stmt__badge {
    display: inline-flex; align-items: center; gap: 5px; margin-top: 12px;
    padding: 5px 10px; border-radius: 8px; font-size: 12px; font-weight: 700;
  }
  .m-stmt__badge--ok  { color: var(--ok);  background: color-mix(in srgb, var(--ok) 12%, transparent); }
  .m-stmt__badge--bad { color: var(--bad); background: color-mix(in srgb, var(--bad) 12%, transparent); }

  /* ── Reports (MobileReportsPage) ──────────────────────────────────────────── */
  .m-rpt-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin-bottom: 4px; }
  .m-rpt-stat {
    display: flex; flex-direction: column; gap: 3px;
    background: var(--bg-card); border: 1px solid var(--line);
    border-radius: var(--m-radius, 12px); padding: 14px; min-width: 0;
  }
  .m-rpt-stat__value { font-size: 23px; font-weight: 700; color: var(--ink); line-height: 1.05; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
  .m-rpt-stat__label { font-size: 12.5px; font-weight: 600; color: var(--ink-2); }
  .m-rpt-stat__sub { font-size: 11px; color: var(--ink-4); }
  .m-rpt__locked { display: flex; align-items: flex-start; gap: 8px; font-size: 12.5px; color: var(--ink-4); line-height: 1.5; }
  .m-rpt__locked svg { color: var(--ink-5); flex-shrink: 0; margin-top: 2px; }
  .m-rpt__gen { margin-top: 20px; }
  .m-rpt__note { font-size: 12px; color: var(--ink-4); line-height: 1.5; margin-top: 12px; text-align: center; }
  @media (max-width: 360px) { .m-rpt-stat__value { font-size: 20px; } }

  /* ── Analyst (MobileAnalystPage) — full-page host for the real CommandBar ──── */
  .m-analyst {
    flex: 1 1 auto; min-height: 0; width: 100%; max-width: 100%;
    display: flex; flex-direction: column; background: var(--bg);
    padding-top: calc(var(--m-header-h, 52px) + var(--m-safe-top, 0px));
    padding-bottom: calc(var(--m-tabbar-h, 64px) + var(--m-safe-bottom, 0px));
    overflow: hidden;
  }
  .m-analyst__body { flex: 1 1 0; min-height: 0; display: flex; position: relative; }
  .m-analyst .app-chat-panel {
    display: flex !important; position: static !important;
    width: 100% !important; height: 100% !important; max-width: 100% !important;
    flex: 1 1 0; border: none !important; background: var(--bg); overflow: hidden;
    /* Same srHidden opacity/pointer-events leak as .m-chat — see note there. */
    opacity: 1 !important; pointer-events: auto !important;
  }
  .m-analyst .cmd-resize-handle,
  .m-analyst .cmd-expand-btn,
  .m-analyst .cmd-chat-head { display: none !important; }
  .m-analyst .cmd-chat-scroll {
    padding: 14px 14px 10px;
    -webkit-mask-image: none; mask-image: none;
    -webkit-overflow-scrolling: touch; overscroll-behavior: contain;
  }
  .m-analyst .cmd-chat-row-user { justify-content: flex-end; }
  .m-analyst .cmd-chat-bubble { font-size: 15px; line-height: 1.55; }
  .m-analyst .cmd-chat-bubble-user {
    background: var(--indigo-soft); border-radius: 18px 18px 5px 18px;
    padding: 9px 14px; max-width: 85%;
  }
  .m-analyst .cmd-chat-composer { margin: 6px 12px calc(10px + var(--m-safe-bottom, 0px)); border-radius: 22px; }
  .m-analyst .cmd-textarea { font-size: 16px; max-height: 130px; }
  .m-analyst .cmd-send, .m-analyst .cmd-stop { width: 34px; height: 34px; }
  .m-analyst .cmd-send:not(:disabled) { background: var(--indigo); color: #fff; }
  .m-analyst .cmd-general-landing {
    flex: 1 1 auto; min-height: 0; align-items: stretch;
    padding: 0 12px calc(10px + var(--m-safe-bottom, 0px));
  }
  .m-analyst .cmd-general-landing-inner { max-width: none; height: 100%; }
  .m-analyst .cmd-general-landing-icon { margin-top: auto; }
  .m-analyst .cmd-general-landing-heading {
    margin-bottom: auto; font-size: 22px; font-weight: 600; text-align: center; padding-bottom: 56px;
  }
  .m-analyst .cmd-general-landing-composer { border-radius: 22px; }
  .m-analyst .cmd-general-landing-composer .cmd-textarea { font-size: 16px; max-height: 130px; }
  /* Hide the CommandBar's own desktop starter chips — mobile draws .m-analyst__chips. */
  .m-analyst .cmd-starter-chips { display: none !important; }
  .m-analyst__chips {
    position: absolute; left: 14px; right: 14px;
    bottom: calc(118px + var(--m-safe-bottom, 0px));
    display: flex; flex-wrap: wrap; gap: 8px; justify-content: center;
    pointer-events: none;
  }

  /* ══ CRM · Contracts · Meetings ═══════════════════════════════════════════ */
  /* Tinted tag chip (shared across CRM / doc / meeting cards + sheets). */
  .m-tag {
    display: inline-flex; align-items: center; flex-shrink: 0;
    padding: 2px 8px; border-radius: 999px;
    font-size: 11px; font-weight: 700; line-height: 1.5;
    white-space: nowrap;
  }

  /* Stage / section group header (Leads by stage, Upcoming/Recent, etc.). */
  .m-crm__group {
    display: flex; align-items: center; gap: 7px;
    font-size: 11px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
    color: var(--ink-4); margin: 14px 0 7px;
  }
  .m-crm__group:first-child { margin-top: 4px; }
  .m-crm__group-n {
    font-size: 11px; font-weight: 700; letter-spacing: 0;
    color: var(--ink-5); background: var(--bg-elev); border-radius: 999px; padding: 1px 7px;
  }

  /* Lead card */
  .m-crm__lead { display: flex; flex-direction: column; gap: 5px; }
  .m-crm__lead-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
  .m-crm__lead-name {
    font-size: 14.5px; font-weight: 600; color: var(--ink); min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .m-crm__lead-val { flex-shrink: 0; font-size: 13px; font-weight: 700; color: var(--ink-2); font-variant-numeric: tabular-nums; }
  .m-crm__lead-meta { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 10px; font-size: 12.5px; color: var(--ink-4); }
  .m-crm__lead-client { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  /* Contact card */
  .m-crm__contact { display: flex; align-items: center; gap: 12px; }
  .m-crm__avatar {
    flex-shrink: 0; width: 38px; height: 38px; border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--indigo-soft); color: var(--indigo);
    font-size: 13px; font-weight: 700;
  }
  .m-crm__avatar--lg { width: 46px; height: 46px; font-size: 15px; }
  .m-crm__avatar--sm { width: 30px; height: 30px; font-size: 11px; }
  .m-crm__contact-body { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
  .m-crm__contact-name { font-size: 14.5px; font-weight: 600; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .m-crm__contact-sub { font-size: 12.5px; color: var(--ink-4); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .m-crm__contact-tags { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 2px; }
  .m-crm__chev { flex-shrink: 0; color: var(--ink-5); display: flex; }

  /* Proposal / contract card */
  .m-crm__doc { display: flex; align-items: center; gap: 10px; }
  .m-crm__doc-body { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
  .m-crm__doc-title { font-size: 14.5px; font-weight: 600; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .m-crm__doc-sub { display: flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--ink-4); min-width: 0; }
  .m-crm__doc-client { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .m-crm__doc-orig { color: var(--indigo); display: flex; flex-shrink: 0; }

  /* Detail-sheet identity block + tags + linked-record rows */
  .m-crm__sheet-id { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
  .m-crm__sheet-id-meta { min-width: 0; }
  .m-crm__sheet-id-name { font-size: 17px; font-weight: 700; color: var(--ink); overflow-wrap: anywhere; }
  .m-crm__sheet-id-sub { font-size: 13px; color: var(--ink-4); margin-top: 2px; overflow-wrap: anywhere; }
  .m-crm__sheet-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 14px; }
  .m-crm__link { color: var(--indigo); text-decoration: none; }
  .m-crm__rec {
    display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
    background: var(--bg-card); border: 1px solid var(--line);
    border-radius: 10px; padding: 10px 12px; margin-bottom: 8px;
    -webkit-tap-highlight-color: transparent; cursor: pointer;
    transition: background-color var(--duration-fast) var(--ease-in-out);
  }
  .m-crm__rec--static { cursor: default; }
  button.m-crm__rec:active { background: var(--bg-sunk, var(--bg-elev)); }
  .m-crm__rec-main { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
  .m-crm__rec-label { font-size: 13.5px; font-weight: 600; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .m-crm__rec-sub { font-size: 11.5px; color: var(--ink-4); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  /* ── Original-file viewer (full-screen overlay) ─────────────────────────── */
  .m-docview {
    position: fixed; inset: 0; z-index: 9600;
    display: flex; flex-direction: column;
    background: var(--bg);
    padding-top: var(--m-safe-top, 0px);
    padding-bottom: var(--m-safe-bottom, 0px);
  }
  .m-docview__head {
    display: flex; align-items: center; gap: 10px;
    height: var(--m-header-h, 52px); flex-shrink: 0;
    padding: 0 12px 0 16px; border-bottom: 1px solid var(--line);
  }
  .m-docview__title {
    flex: 1 1 0; min-width: 0; font-size: 15px; font-weight: 700; color: var(--ink);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .m-docview__close {
    flex-shrink: 0; width: var(--m-touch, 44px); height: var(--m-touch, 44px);
    display: inline-flex; align-items: center; justify-content: center;
    background: none; border: none; color: var(--ink-3); cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .m-docview__close:active { color: var(--ink); }
  .m-docview__body { flex: 1 1 0; min-height: 0; display: flex; overflow: hidden; }
  .m-docview__body .m-empty { margin: auto; text-align: center; padding: 24px; }
  .m-docview__frame { flex: 1 1 0; width: 100%; height: 100%; border: 0; background: var(--bg-elev); }
  .m-docview__foot {
    flex-shrink: 0; padding: 12px 16px calc(12px + var(--m-safe-bottom, 0px));
    border-top: 1px solid var(--line);
  }
  .m-docview__foot .m-btn--block { margin-top: 0; }

  /* ── Meetings ───────────────────────────────────────────────────────────── */
  .m-mtg-actions { display: flex; gap: 10px; margin-bottom: 6px; }
  .m-mtg-actions .m-action { flex: 1 1 0; justify-content: center; }
  .m-mtg-action--filled { background: var(--indigo); border-color: var(--indigo); color: #fff; }
  .m-mtg-action--filled svg { color: #fff; }
  .m-mtg { display: flex; align-items: stretch; gap: 10px; padding: 12px 14px; }
  .m-mtg__main {
    flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 4px;
    background: none; border: none; padding: 0; text-align: left; cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .m-mtg__head { display: flex; align-items: center; gap: 8px; min-width: 0; }
  .m-mtg__title {
    font-size: 14.5px; font-weight: 600; color: var(--ink); min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .m-mtg__meta { font-size: 12.5px; color: var(--ink-3); }
  .m-mtg__meta2 { display: flex; flex-wrap: wrap; gap: 4px 10px; font-size: 12px; color: var(--ink-4); }
  .m-mtg__proj { color: var(--indigo); font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .m-mtg__join { flex-shrink: 0; align-self: center; min-height: var(--m-touch, 44px); padding: 0 16px; margin-top: 0; }
  .m-mtg__att { display: flex; align-items: center; gap: 10px; padding: 6px 0; }
  .m-mtg__att-meta { min-width: 0; display: flex; flex-direction: column; }
  .m-mtg__att-name { font-size: 13.5px; font-weight: 600; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .m-mtg__att-sub { font-size: 11.5px; color: var(--ink-4); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .m-mtg__action { display: flex; align-items: flex-start; gap: 9px; padding: 6px 0; }
  .m-mtg__action-dot { flex-shrink: 0; width: 7px; height: 7px; border-radius: 50%; margin-top: 6px; background: var(--warn); }
  .m-mtg__action--done .m-mtg__action-dot { background: var(--ok); }
  .m-mtg__action-text { font-size: 13.5px; color: var(--ink-2); line-height: 1.45; }
  .m-mtg__action--done .m-mtg__action-text { color: var(--ink-4); text-decoration: line-through; }

  /* ── Full-width primary action button (Invite / Upload / New document) ────── */
  .m-fullbtn { display: flex; width: 100%; margin: 0 0 14px; }

  /* ── Members ──────────────────────────────────────────────────────────────── */
  /* Team cards reuse the .m-crm__contact layout; avatar photo fills the disc. */

  /* ── Deadlines ────────────────────────────────────────────────────────────── */
  .m-dl { display: flex; flex-direction: column; gap: 5px; }
  .m-dl__head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
  .m-dl__title {
    min-width: 0; flex: 1 1 0;
    font-size: 14.5px; font-weight: 600; color: var(--ink);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .m-dl__proj { font-size: 12.5px; color: var(--indigo); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .m-dl__meta { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 10px; font-size: 12.5px; color: var(--ink-4); }
  .m-dl__due { font-variant-numeric: tabular-nums; }
  .m-dl__due--late { color: var(--bad); font-weight: 600; }

  /* ── Intake ───────────────────────────────────────────────────────────────── */
  .m-intake__form { display: flex; flex-direction: column; }
  .m-intake__area {
    min-height: 180px; padding: 12px; line-height: 1.5;
    resize: vertical; -webkit-appearance: none;
  }
  .m-intake__preview {
    max-height: 220px; overflow-y: auto; overscroll-behavior: contain;
    white-space: pre-wrap; font-size: 12.5px;
    background: var(--bg-elev); border: 1px solid var(--line);
    border-radius: 10px; padding: 12px; margin-top: 12px;
  }

  /* ── Admin ────────────────────────────────────────────────────────────────── */
  /* 6 metric tiles in the shared 3-col stat grid → 2 rows; value stays legible. */
  .m-admin__stats { margin-top: 0; margin-bottom: 4px; }
  .m-admin__stats .m-stat { align-items: flex-start; text-align: left; }
  .m-admin__stats .m-stat__value { font-size: 20px; }

  /* ── Activity feed ────────────────────────────────────────────────────────── */
  .m-act { display: flex; align-items: flex-start; gap: 11px; }
  .m-act__dot { flex-shrink: 0; width: 8px; height: 8px; border-radius: 50%; margin-top: 6px; }
  .m-act__body { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
  .m-act__title { font-size: 13.5px; color: var(--ink); line-height: 1.4; }
  .m-act__summary { color: var(--ink-3); font-weight: 400; }
  .m-act__meta { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 8px; font-size: 11.5px; color: var(--ink-4); }
  .m-act__proj { color: var(--indigo); font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .m-act__unread { flex-shrink: 0; width: 8px; height: 8px; border-radius: 50%; background: var(--indigo); margin-top: 6px; }

  /* ── Studio Review (MobileStudioReviewPage) ─────────────────────────────────
     List: sessions grouped by project (reuses .m-crm__group). Session view:
     back bar + header + segmented Sheets|Comments|Markups, comment composer,
     read-only markup list. Sheets open the shared .m-docview overlay. */

  /* Session card (list) */
  .m-sr__sess { display: flex; flex-direction: column; gap: 6px; }
  .m-sr__sess-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
  .m-sr__sess-name {
    flex: 1 1 0; min-width: 0;
    font-size: 14.5px; font-weight: 600; color: var(--ink);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .m-sr__sess-meta { display: flex; flex-wrap: wrap; gap: 4px 12px; font-size: 12px; color: var(--ink-4); }

  /* Back bar */
  .m-sr__back {
    display: inline-flex; align-items: center; gap: 4px;
    background: none; border: none; padding: 4px 2px; margin: 0 0 6px -2px;
    min-height: var(--m-touch, 44px);
    font-size: 13.5px; font-weight: 600; color: var(--indigo);
    cursor: pointer; -webkit-tap-highlight-color: transparent;
  }
  .m-sr__back:active { opacity: 0.6; }
  .m-sr__back svg { color: var(--indigo); }

  /* Session header */
  .m-sr__shead { margin-bottom: 12px; }
  .m-sr__stitle { font-size: 20px; font-weight: 700; color: var(--ink); line-height: 1.22; }
  .m-sr__smeta { display: flex; flex-wrap: wrap; gap: 4px 10px; font-size: 12.5px; color: var(--ink-4); margin-top: 5px; }
  .m-sr__sproj { color: var(--indigo); font-weight: 600; }
  .m-sr__shead .m-crm__sheet-tags { margin-top: 8px; }

  /* Sheet / file row */
  .m-sr__file { display: flex; align-items: center; gap: 11px; text-align: left; }
  .m-sr__file:disabled { opacity: 0.6; }
  .m-sr__file-ic { flex-shrink: 0; display: flex; color: var(--ink-4); }
  .m-sr__file-body { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
  .m-sr__file-name {
    font-size: 14px; font-weight: 600; color: var(--ink);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .m-sr__file-sub {
    font-size: 12px; color: var(--ink-4);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }

  /* Comment composer */
  .m-sr__composer {
    display: flex; flex-direction: column; gap: 8px;
    background: var(--bg-elev); border: 1px solid var(--line);
    border-radius: var(--m-radius, 12px); padding: 10px; margin-bottom: 12px;
  }
  .m-sr__composer-input {
    width: 100%; resize: vertical; min-height: 44px; max-height: 160px;
    font-size: 16px; line-height: 1.45; color: var(--ink);
    background: var(--bg); border: 1px solid var(--line);
    border-radius: 9px; padding: 9px 11px; -webkit-appearance: none;
  }
  .m-sr__composer-input:focus-visible { outline: 2px solid var(--indigo); outline-offset: 1px; }
  .m-sr__composer-foot { display: flex; align-items: center; justify-content: flex-end; gap: 10px; }
  .m-sr__composer-err { flex: 1 1 0; min-width: 0; font-size: 12px; color: var(--bad); }
  .m-sr__composer-send { margin-top: 0; min-height: var(--m-touch, 44px); padding: 0 20px; width: auto; }
  .m-sr__composer-send:disabled { opacity: 0.5; }

  /* Comment card */
  .m-sr__cmt { display: flex; flex-direction: column; gap: 7px; }
  .m-sr__cmt-top { display: flex; align-items: center; gap: 8px; }
  .m-sr__cmt-who {
    flex: 1 1 0; min-width: 0;
    font-size: 13px; font-weight: 600; color: var(--ink);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .m-sr__cmt-body { font-size: 13.5px; color: var(--ink-2); line-height: 1.5; white-space: pre-wrap; word-break: break-word; }
  .m-sr__cmt-meta { display: flex; flex-wrap: wrap; gap: 3px 10px; font-size: 11.5px; color: var(--ink-4); }

  /* Markup note + read-only card */
  .m-sr__note {
    display: flex; align-items: flex-start; gap: 8px;
    font-size: 12.5px; color: var(--ink-3); line-height: 1.45;
    background: color-mix(in srgb, var(--indigo) 8%, transparent);
    border: 1px solid color-mix(in srgb, var(--indigo) 22%, var(--line));
    border-radius: 10px; padding: 10px 12px; margin-bottom: 12px;
  }
  .m-sr__note svg { flex-shrink: 0; margin-top: 1px; color: var(--indigo); }
  .m-sr__markup { display: flex; flex-direction: column; gap: 6px; }
  .m-sr__markup-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
  .m-sr__markup-subj {
    flex: 1 1 0; min-width: 0;
    font-size: 13.5px; font-weight: 600; color: var(--ink);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .m-sr__markup-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; font-size: 11.5px; color: var(--ink-4); }
  .m-sr__markup-tool { text-transform: capitalize; font-weight: 600; color: var(--ink-3); }

} /* end @media (max-width: 768px) — workspace rules above this line */

/* ============================================================================
   LANDING FIXES — public, NOT preview-gated (the landing is live on phones
   today). Conservative, ≤768px-scoped, layout-only. Desktop byte-identical.
   Audited live 2026-06-10 at 320/375/430px via same-origin iframes.
   ============================================================================ */
@media (max-width: 768px), ((pointer: coarse) and (max-height: 500px)) {

  /* FIX 1 — Footer link columns clipped off-screen.
     .landing-footer-inner is grid `1fr auto`; at phone widths the brand
     column eats the row and the link columns land at x≈350+ → clipped by
     .landing-wrap overflow:hidden → Product/Company/Resources/Contact links
     were UNREACHABLE on every phone. Stack the grid. */
  .landing-footer-inner { grid-template-columns: 1fr; gap: 36px; }
  .landing-footer-brand { max-width: 100%; }

  /* FIX 2 — Hero command-center mock crushed + clipped.
     .hcc-ai-col is a fixed 190px (246px wide-state) flex child, leaving the
     command-center pane ~110px at 375px — its topbar buttons, KPI numbers and
     chart controls all clipped mid-glyph. Make the AI column proportional and
     drop the decorative chrome that can't fit. (Scoped to .hcc-frame — the
     real workspace shares some inner class names and must not be touched.) */
  .hcc-ai-col, .hcc-ai-col-wide { width: 42%; min-width: 128px; }
  .hcc-frame .hcc-topbar-right { display: none; }
  .hcc-frame .pf-controls { display: none; }
  .hcc-frame .grid-2 { grid-template-columns: 1fr; }
  /* R4: 3-across left ~60px per KPI card at 375 — "BUSINES HEALTH" / "$18.4"
     clipped mid-glyph. 2×3 with compact labels; decorative footnotes off. */
  .hcc-frame .grid-metrics { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .hcc-frame .metric-label { font-size: 8.5px; letter-spacing: 0.05em; }
  .hcc-frame .metric-foot { display: none; }
  .hcc-frame .metric-card { min-width: 0; overflow: hidden; }
  .hcc-frame .numstat-lg .numstat-value { font-size: 13px; letter-spacing: -0.02em; }
  .hcc-frame .card { min-width: 0; max-width: 100%; overflow: hidden; }
  /* FIX 2b — data table inside the mock clipped ~11px past 320px viewports.
     Decorative content: clamp + hide (no scroll affordance needed in a mock). */
  .hcc-frame .tbl { display: block; max-width: 100%; overflow: hidden; }
  /* R4: SE-class widths — "OUTSTANDING A/R" / "AVG UTILIZATION" clipped
     mid-word in the ~78px KPI cards; tighten the label one step further. */
  @media (max-width: 380px) {
    .hcc-frame .metric-label { font-size: 8px; letter-spacing: 0.02em; }
  }

  /* FIX 3 — Comparison table: horizontally scrollable (7 columns, 1100px min)
     but with zero affordance — on a phone it reads as a broken half-table.
     Sticky swipe hint inside the scroll container (founder rule #3: overflowing
     strips get explicit swipe affordance). */
  .ls-vs-wrap::before {
    content: "Swipe to compare \2192";
    display: block;
    position: sticky; left: 0;
    width: max-content;
    font-size: 12px; font-weight: 700; color: var(--indigo);
    padding: 2px 2px 8px;
  }

  /* FIX 4 — Studio Review feature card showed an EMPTY WHITE BOX on phones
     (founder iPhone, 2026-06-10). Root cause: styles.css's generic ≤768px
     full-bleed rule for the standalone demo —
       .srd-shell { width:100vw; margin-left:50%; transform:translateX(-50%) }
     — leaks into the card's cropped thumbnail. The crop selector
     (.fc-sr-thumb .srd-shell: width 325.71%, left −161.9%) out-specifies
     width/margin but sets NO transform, so translateX(-50%) of the ~3.25×
     oversized shell shifts the whole screenshot ≈1060px further left — the
     thumb window ends up past the image's right edge → bare card background.
     Neutralizing the transform restores the static composed frame: the thumb
     already freezes the SVG overlay on its final populated state
     (animation:none + final-state base keyframe values), so it renders
     immediately with no animation dependency. PUBLIC, ≤768px only. */
  .fc-sr-thumb .srd-shell { transform: none; margin: 0; }
  /* Same translateX/100vw leak hits the click-to-expand lightbox demo. */
  .fc-modal-demo .srd-shell, .fc-modal-panel .srd-shell {
    transform: none; margin: 0; width: 100%;
  }

} /* end landing fixes — nothing below this line */

/* ── Landing scroll-reveal kill switch (phones) ──────────────────────────────
   The IntersectionObserver reveal gating proved unreliable on iOS Safari —
   founder's phone showed THE SOLUTION as an empty gray band (nodes/lines
   stuck at opacity 0 because .is-on never landed) — and the draw-in
   transitions contribute first-load jank on phones. On ≤768px the landing
   shows everything immediately; reveal animation remains desktop-only.
   PUBLIC (not preview-flag gated): the landing is live on phones today. */
@media (max-width: 768px), ((pointer: coarse) and (max-height: 500px)) {
  .ls-sol-line,
  .ls-prob-panel, .ls-prob-record,
  .ls-proof-grid .ls-proof-col, .ls-proof-foot,
  .ls-wf-grid .ls-wf-card,
  .ls-vs-wrap,
  .ls-sec-stack .ls-sec-layer,
  .ls-built-sheet .ls-built-spoke, .ls-built-sheet .ls-built-node,
  .ls-built-sheet .ls-built-label, .ls-built-sheet .ls-built-axis,
  .ls-built-sheet .ls-built-draft path, .ls-built-sheet .ls-built-draft circle,
  .ls-built-sheet .ls-built-core, .ls-built-sheet .ls-built-coredot,
  .ls-built-sheet .ls-built-mark, .ls-built-sheet .ls-built-grid line,
  .intg-grid .intg-card, .about-values .about-value,
  .rm-grid .rm-col, .secpage-blocks .secpage-block {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  .ls-sol-line, .ls-built-draft path, .ls-built-spoke {
    stroke-dashoffset: 0 !important;
    stroke-dasharray: none !important;
  }
  /* Node pills + hub force-visible like the families above, but they MUST keep
     their translate(-50%,-50%) centering transform — a blanket transform:none
     detaches the spokes from the hub and shoves every pill off-center. So they
     get their own rule that resets only opacity/transition. */
  .ls-sol-node, .ls-sol-hub {
    opacity: 1 !important;
    transition: none !important;
  }
  /* The product feature cards (.fc-*-card incl. Studio Review) gate on the
     same IntersectionObserver pattern via .sr-reveal/.sr-visible — force
     visible on phones for the same reason as the families above. */
  .sr-reveal {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }

  /* ── Offices (MobileOfficesPage + MobileOfficePage) ───────────────────────── */
  .m-office { display: flex; flex-direction: column; gap: 8px; }
  .m-office__head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
  .m-office__id { display: flex; align-items: center; gap: 8px; min-width: 0; }
  .m-office__dot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; background: var(--ink-5); }
  .m-office__name { font-size: 16px; font-weight: 700; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .m-office__loc { font-size: 12.5px; color: var(--ink-4); }
  .m-office__stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 12px; margin-top: 2px; }
  .m-office__stat { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
  .m-office__stat b { font-size: 15px; font-weight: 700; color: var(--ink); line-height: 1.2; overflow-wrap: anywhere; }
  .m-office__stat i { font-size: 10.5px; font-style: normal; color: var(--ink-4); }
  .m-office__chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 2px; }

  .m-office-detail__id { margin-bottom: 14px; }
  .m-office-detail__name { display: flex; align-items: center; gap: 8px; font-size: 22px; font-weight: 700; color: var(--ink); line-height: 1.2; }
  .m-office-detail__sub { font-size: 13px; color: var(--ink-4); margin-top: 4px; }
  .m-office__meta { margin-bottom: 14px; }
  .m-office__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); margin-top: 0; }
  .m-office__grid .m-stat { align-items: flex-start; text-align: left; }
  .m-office__grid .m-stat__value { font-size: 18px; overflow-wrap: anywhere; }
  .m-office__locked-stat { flex-direction: row; align-items: center; gap: 8px; color: var(--ink-4); }
  .m-office__locked-stat svg { color: var(--ink-5); }

  .m-office__review { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 12px; border-color: color-mix(in srgb, var(--warn) 45%, var(--line)); }
  .m-office__review-body { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
  .m-office__review-n { font-size: 22px; font-weight: 800; color: var(--warn); line-height: 1; }
  .m-office__review-l { font-size: 13px; color: var(--ink-2); }

  .m-office__acct { display: flex; flex-direction: column; gap: 5px; }
  .m-office__acct-top { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
  .m-office__acct-name { font-size: 14.5px; font-weight: 600; color: var(--ink); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .m-office__acct-bal { font-size: 15px; font-weight: 700; color: var(--ink); white-space: nowrap; }
  /* Credit card = money owed. The "−" is in the number and the meta line below
     says "Credit card", so colour is not carrying this alone. */
  .m-office__acct-bal--debt { color: var(--bad); }
  .m-office__acct-meta { font-size: 11.5px; color: var(--ink-4); }
  .m-office__acct-summary { font-size: 12px; color: var(--ink-4); line-height: 1.5; margin-top: 12px; }

  .m-office__member { display: flex; align-items: center; gap: 11px; }
  .m-office__util { font-size: 12px; font-weight: 700; color: var(--indigo); flex-shrink: 0; }
}
