/* ============================================================================
   MOBILE SHELL — stage (a) of Josh's mobile overhaul ruling (2026-08-01).
   Loads LAST, after paper.css, and owns everything <=640px that the ruling
   moved: the pill search + filter chips up top, the four-tab bottom nav,
   the retired hamburger, the Noir map grade, spacing/radius discipline.

   THE GRAMMAR IS GOOGLE MAPS', THE PAINT IS TILFULLY'S: paper surfaces
   (--p-*), the deep emerald action green (--t-emerald), system type.
   One metric system, used by every surface here:
     --m-top     breathing room under the status bar (Josh likes the air)
     --m-x       screen gutter
     --m-pill-h  the search pill
     --m-chip-h  the filter chips
     --m-nav-h   the bottom nav (labels included, safe-area added on top)
     --m-radius  cards & sheets     --m-round  pills & chips (full round)
   Rendered by src/shell/mobile-shell.js; body.m-shell gates every rule so
   desktop never sees any of this even if a rule leaks past the media query.
   ========================================================================== */
:root {
  /* SAFARI-PROOF TOP (Josh, 2026-08-01): this runs in mobile Safari — the
     URL bar overlays the top and env() reads ZERO in browser mode. A floor
     carries the clearance there; standalone keeps the real inset. +20px of
     Google-style air on top of either. Global: every tab's top bar. */
  --m-top: calc(max(env(safe-area-inset-top, 0px), 14px) + 6px);   /* higher (Josh, 2026-08-02 eve) */
  --m-x: 12px;
  --m-pill-h: 52px;   /* thicker again (Josh, 2026-08-02 eve) — all tabs */
  --m-chip-h: 34px;
  --m-nav-h: 60px;
  /* Safari's collapsing bottom toolbar covers flush-bottom UI — an 18px
     floor lifts the nav clear in browser mode; standalone keeps the inset */
  --m-nav-pad: max(env(safe-area-inset-bottom, 0px), 18px);
  --m-sheet-peek: 64px;
  --m-radius: 16px;
  --m-round: 999px;
  /* 2026 RECOLOR (Josh, 2026-08-01: "green buttons... 2010 android vibes.
     Make it 2026 colors."): mobile controls ride the app's own monochrome
     ACTION language — ink buttons, black in day / white in night, the same
     tokens the paper skin already speaks. Green survives only where it MEANS
     something (map pins, semantic statuses) and in the sprout mark, which is
     the logo. --m-wash is the quiet active tint. */
  --m-wash: rgba(29, 29, 31, 0.07);
  --m-wash-hi: rgba(29, 29, 31, 0.12);
  --m-brand: #157a4d;          /* the sprout mark only */
  /* the TAPPABLE tint (Josh: not green — "that yellow that's used when
     something's highlighted… more modern"): the brand gold, muted */
  --m-link: #8a6a08;
}
body.night-mode {
  --m-wash: rgba(245, 245, 244, 0.1);
  --m-wash-hi: rgba(245, 245, 244, 0.17);
  --m-brand: #3fae7d;
  --m-link: #edc55b;
}
/* TRUE-BLACK NIGHT on the phone (Josh: "really really dark and clean") —
   the paper night surfaces sink to near-black under the mobile shell */
body.night-mode.m-shell {
  /* ONE BLACK (Josh's ruling, 2026-08-01): the page, the list, and the rows
     all sit on the SAME black as the nav bar — no lifted panels. #060607
     everywhere; rows separated only by the hairline. */
  --p-canvas: #060607;
  --p-card: #0e0e10;
  --p-card-2: #0b0b0c;
  --p-hair: rgba(255, 255, 255, 0.085);   /* ~#242426 on the black */
  --p-hair-hi: rgba(255, 255, 255, 0.16);
}
body.night-mode.m-shell,
body.night-mode.m-shell #appView,
body.night-mode.m-shell #appView main,
body.night-mode.m-shell #appView main > section.page {
  background: #060607 !important;
}

@media (max-width: 640px) {

  /* ---- the hamburger is dead (ruling §1): the bottom nav is the nav ------ */
  body.m-shell .map-menu-btn { display: none !important; }
  body.m-shell #phoneMenuRoot { display: none !important; }

  /* ---- TOP BAR: pill search + avatar, chips row underneath --------------- */
  #mobileTopBar {
    position: fixed;
    top: 0; left: 0; right: 0;
    z-index: 48;
    padding: var(--m-top) var(--m-x) 8px;
    pointer-events: none;             /* the bar is air; its children are real */
    display: flex; flex-direction: column; gap: 8px;
    /* OPAQUE (Josh's IMG_0978: rows bled through the fixed bar on scroll) */
    background: var(--p-canvas);
    border-bottom: 1px solid var(--p-hair);
  }
  body.night-mode #mobileTopBar { background: #060607; }
  /* HIDE-ON-SCROLL (Josh, 2026-08-02): scrolling down tucks the chrome
     away; scrolling up brings it back. Home keeps its own rules. */
  #mobileTopBar { transition: transform 0.24s ease; will-change: transform; }
  body.m-chrome-hidden #mobileTopBar:not(.m-home-bar) { transform: translateY(-110%); }
  body.m-shell #cold .cold-list-strip { transition: transform 0.24s ease; }
  body.m-chrome-hidden #cold .cold-list-strip {
    /* the strip leaves WITH the chrome (Josh: "when I scroll I won't see
       it") and returns on any upward scroll */
    transform: translateY(-300%);
  }
  /* HOME: chips only, floating over the map below the pill — transparent */
  #mobileTopBar.m-home-bar {
    background: transparent !important;
    border-bottom: 0 !important;
    top: calc(var(--m-top) + var(--m-pill-h) + 10px);
    padding: 0 var(--m-x);
  }
  body.m-shell #overview .map-filter-bar { display: none !important; }  /* the chips replaced it */
  #mobileTopBar .m-pill-row {
    display: flex; align-items: center; gap: 8px;
    pointer-events: none;
  }
  #mobileTopBar .m-search {
    flex: 1 1 auto; display: flex; align-items: center; gap: 10px;
    height: var(--m-pill-h);
    padding: 0 7px 0 14px;
    border-radius: var(--m-round);
    background: var(--p-card);
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.16);
    pointer-events: auto;
  }
  /* the pill's full anatomy (Josh's IMG_0936 ruling): the tilted sprout mark
     on the left, the avatar inside the oval on the right */
  .m-sprout {
    display: inline-flex; flex: 0 0 auto;
    width: 22px; height: 22px;
    color: var(--m-brand);
    transform: rotate(-12deg);           /* the tilt IS the logo */
  }
  .m-sprout svg { width: 100%; height: 100%; }
  body.night-mode #mobileTopBar .m-search { background: #121214; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.4); }
  #mobileTopBar .m-search svg.m-glyph {
    width: 19px; height: 19px; flex: 0 0 auto;
    color: var(--p-ink-faint);
  }
  #mobileTopBar .m-search input {
    flex: 1 1 auto; min-width: 0;
    height: 100%;
    border: 0 !important; background: transparent !important;
    font-size: 16px !important;       /* iOS focus-zoom rule — never smaller */
    color: var(--p-ink) !important;
    outline: none; box-shadow: none !important; padding: 0 !important;
  }
  #mobileTopBar .m-search input::placeholder { color: var(--p-ink-faint); }
  /* the avatar lives INSIDE the pill's right end — Profile & Settings moved
     here when the hamburger died (Google's own grammar) */
  .m-avatar {
    flex: 0 0 auto;
    width: 34px; height: 34px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%; border: 0; padding: 0;
    background: var(--t-action); color: var(--t-action-ink);
    font-size: 0.8rem; font-weight: 700; letter-spacing: 0.02em;
    pointer-events: auto; cursor: pointer;
  }
  .m-avatar:active { transform: scale(0.94); }

  /* ---- FILTER CHIPS (ruling §1): the tab's REAL filters, thumb pills.
     ONE LINE on Prospects (Josh, 2026-08-01): [+] pinned left, chips
     scrolling in the middle, the live 0/N counter pinned right. ---------- */
  #mobileTopBar .m-chiprow {
    flex-wrap: nowrap;
    display: flex; align-items: center; gap: 8px;
    pointer-events: auto;
  }
  #mobileTopBar .m-chips {
    flex: 1 1 auto; min-width: 0;
    display: flex; align-items: center; gap: 8px;
    overflow-x: auto; -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding: 2px 2px 6px;
  }
  #mobileTopBar .m-plus {
    flex: 0 0 auto;
    width: var(--m-chip-h); height: var(--m-chip-h);
    display: inline-flex; align-items: center; justify-content: center;
    border: 0; border-radius: 50%;
    background: var(--t-action); color: var(--t-action-ink);
    font-size: 1.25rem; line-height: 1; font-weight: 600;
    box-shadow: 0 1px 6px rgba(0, 0, 0, 0.18);
    cursor: pointer;
  }
  #mobileTopBar .m-plus:active { transform: scale(0.94); }
  /* the 0/N calls-today hero, pinned at the row's right (Josh: "I want to
     be able to see the hero 0/25 on the row on the right side") */
  #mobileTopBar .m-score {
    flex: 0 0 auto;
    display: inline-flex; flex-direction: column; gap: 3px;
    justify-content: center;
    height: var(--m-chip-h);
    padding: 0 12px;
    border-radius: var(--m-round);
    background: var(--p-card);
    box-shadow: 0 1px 6px rgba(0, 0, 0, 0.12);
    font-size: 0.8rem; color: var(--p-ink-soft);
    font-variant-numeric: tabular-nums;
  }
  body.night-mode #mobileTopBar .m-score { background: #121214; box-shadow: 0 1px 6px rgba(0, 0, 0, 0.35); }
  #mobileTopBar .m-score strong { color: var(--p-ink); font-weight: 750; }
  #mobileTopBar .m-score .m-score-bar {
    display: block; height: 3px; border-radius: 2px; overflow: hidden;
    background: var(--m-wash);
  }
  #mobileTopBar .m-score .m-score-bar b { display: block; height: 100%; background: var(--p-ink); border-radius: 2px; }
  #mobileTopBar .m-score.hit { box-shadow: inset 0 0 0 1.5px var(--p-ink); }
  #mobileTopBar .m-chips::-webkit-scrollbar { display: none; }
  #mobileTopBar .m-chip {
    flex: 0 0 auto;
    display: inline-flex; align-items: center; gap: 6px;
    height: var(--m-chip-h);
    padding: 0 14px;
    border: 0; border-radius: var(--m-round);
    background: var(--p-card); color: var(--p-ink);
    font-size: 0.82rem; font-weight: 600;
    box-shadow: 0 1px 6px rgba(0, 0, 0, 0.12);
    cursor: pointer; white-space: nowrap;
  }
  body.night-mode #mobileTopBar .m-chip { background: #121214; box-shadow: 0 1px 6px rgba(0, 0, 0, 0.35); }
  #mobileTopBar .m-chip strong {
    font-weight: 700; font-size: 0.78rem;
    color: var(--p-ink-faint); font-variant-numeric: tabular-nums;
  }
  /* active chip: the moss wash LAYERED on the card color — a translucent
     background alone let page content bleed through the fixed chip */
  #mobileTopBar .m-chip.active,
  body.night-mode #mobileTopBar .m-chip.active {
    /* the night selector is REQUIRED, not belt-and-braces: the night base
       chip rule above carries one more element and out-ranked .active —
       the invisible dark-on-dark "All" chip in the night review shot */
    background: var(--t-action);
    color: var(--t-action-ink);
    box-shadow: 0 1px 6px rgba(0, 0, 0, 0.18);
  }
  #mobileTopBar .m-chip.active strong,
  body.night-mode #mobileTopBar .m-chip.active strong { color: var(--t-action-ink); opacity: 0.75; }
  #mobileTopBar .m-chip:active { transform: scale(0.96); }

  /* ---- content clearance: pages duck under the fixed bars ---------------- */
  /* the top bar's real height: pill row + (chips, when the tab has them).
     :not(#overview) is LOAD-BEARING SPECIFICITY, not just scoping — phase4's
     52px rule carries :not(#overview), and :not(#id) counts as an ID (the
     house scar); matching its shape is the only way to outrank it. */
  body.m-shell #appView main > section.page:not(#overview) {
    padding-top: calc(var(--m-top) + var(--m-pill-h) + 12px) !important;
    padding-bottom: calc(var(--m-nav-h) + var(--m-nav-pad) + 12px) !important;
  }
  body.m-shell.m-has-chips #appView main > section.page:not(#overview) {
    padding-top: calc(var(--m-top) + var(--m-pill-h) + 8px + var(--m-chip-h) + 14px) !important;
  }
  /* the map IS the screen: no top padding, the pill floats over it */
  body.m-shell #appView main > section.page#overview {
    padding-top: 0 !important;
    padding-bottom: 0 !important;
  }
  body.m-shell #appView main {
    padding-top: 0 !important;
    padding-bottom: 0 !important;
  }

  /* ---- HOME (the map tab): existing search pill adopts the new metrics ---
     The map's own search (places + accounts) stays the ONE search on Home —
     mobile-shell renders no duplicate there; these rules align it to the
     pill grammar (geometry only; its handlers are untouched). The avatar
     chip rides in #mobileTopBar above it. */
  /* the WRAPPER is the pill (paper.css round 11 already makes the input
     transparent inside it) — double-id matches paper's frosted-glass rule,
     which otherwise wins and leaves the washed-grey veil from the first
     day-mode review shot */
  body.m-shell #appView #overview .dash-map-hero .map-search {
    position: fixed !important;
    left: var(--m-x) !important;
    right: var(--m-x) !important;      /* full width — the avatar rides INSIDE */
    top: var(--m-top) !important;
    width: auto !important; max-width: none !important;
    height: var(--m-pill-h);
    display: flex !important; align-items: center;
    z-index: 47;                                   /* under #mobileTopBar's 48 */
    border-radius: var(--m-round) !important;
    border: 0 !important;
    backdrop-filter: none !important; -webkit-backdrop-filter: none !important;
    background: #ffffff !important;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.16) !important;
    padding: 0 !important; transform: none !important;
  }
  body.night-mode.m-shell #appView #overview .dash-map-hero .map-search {
    background: #141416 !important;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.4) !important;
  }
  body.m-shell #overview .map-search input {
    height: 100% !important; width: 100%; flex: 1 1 auto; min-width: 0;
    padding-left: 44px !important;
    padding-right: 84px !important;    /* funnel + avatar live inside the oval */
  }
  body.night-mode.m-shell #overview .map-search input { color: #f2f2f4 !important; }
  body:not(.night-mode).m-shell #overview .map-search input { color: #202124 !important; }
  /* the magnifier yields to the sprout mark (dressed in by mobile-shell) */
  body.m-shell #overview .map-search .map-search-glyph { display: none !important; }
  body.m-shell #overview .map-search .m-sprout {
    position: absolute; left: 14px; top: 50%;
    transform: translateY(-50%) rotate(-12deg);
  }
  body.m-shell #overview .map-search .m-avatar {
    position: absolute; right: 7px; top: 50%; transform: translateY(-50%);
  }
  body.m-shell #overview .map-search .m-avatar:active { transform: translateY(-50%) scale(0.94); }
  body.m-shell #overview .map-filter-inline { right: 48px !important; top: 50%; transform: translateY(-50%); }
  body.m-shell #overview .dash-map-hero .map-filter-bar { top: calc(var(--m-top) + var(--m-pill-h) + 10px); }

  /* ---- THE NOIR GRADE (ruling §3) ----------------------------------------
     The map constructs on the DARK base at phone width (workspace-map.js);
     this grade desaturates the land to slate, sinks the water toward
     #08101C, and dims the labels — Google's DOM puts the vector tiles on a
     <canvas> and AdvancedMarkerElement pins in a sibling HTML layer, so the
     filter touches ONLY the tiles: pin colors are untouched, per the ruling.
     (The style-JSON route is closed under a mapId — see workspace-map.js.) */
  body.night-mode.m-shell #overview .gm-style canvas,
  body.night-mode.m-shell #overview .gm-style img {
    /* canvas = vector tiles; img = raster tiles (DEMO_MAP_ID renders raster).
       Pins are plain divs (.google-status-marker) in a sibling layer — never
       filtered, per the ruling. */
    filter: saturate(0.25) brightness(0.9) contrast(1.06) hue-rotate(-6deg);
  }

  /* ---- BOTTOM NAV (ruling §2): Home · Accounts · Prospects · Activity ---- */
  #mobileTabBar {
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 48;
    display: flex; align-items: stretch;
    /* the label row needs a floor even with no home indicator (the clipped-
       labels screenshot, first review pass) */
    height: calc(var(--m-nav-h) + var(--m-nav-pad));
    padding: 6px var(--m-x) var(--m-nav-pad);
    background: rgba(255, 255, 255, 0.96);
    -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px);
    border-top: 1px solid var(--p-hair);
  }
  body.night-mode #mobileTabBar {
    background: rgba(6, 6, 7, 0.97);          /* THE black — same value as the page */
    border-top-color: rgba(255, 255, 255, 0.07);
  }
  #mobileTabBar .m-tab {
    flex: 1 1 0; min-width: 0;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 3px;
    border: 0; background: transparent; padding: 0;
    color: var(--p-ink);            /* white icons (Josh) — active shows via the wash */
    cursor: pointer;
  }
  /* icon-only nav (Josh: "don't need to say Home or prospect… just the
     icons, more modern") — labels gone, glyphs carry it */
  #mobileTabBar .m-tab span:not(.m-tab-glyph) { display: none; }
  #mobileTabBar .m-tab .m-tab-glyph {
    display: inline-flex; align-items: center; justify-content: center;
    width: 60px; height: 38px;
    border-radius: var(--m-round);
    transition: background 0.15s ease;
  }
  #mobileTabBar .m-tab svg { width: 25px; height: 25px; }
  #mobileTabBar .m-tab.active { color: var(--p-ink); }
  #mobileTabBar .m-tab.active .m-tab-glyph { background: var(--m-wash); }
  #mobileTabBar .m-tab:active .m-tab-glyph { background: var(--m-wash-hi); }

  /* the chat sheet owns the whole screen — both bars step aside (the same
     contract the FAB and hamburger already followed) */
  body.donna-sheet-open #mobileTabBar, body:has(#donnaDock.open) #mobileTabBar,
  body.donna-sheet-open #mobileTopBar, body:has(#donnaDock.open) #mobileTopBar {
    display: none !important;
  }

  /* ---- floats clear the new bottom nav ----------------------------------- */
  body.m-shell #threadBadgeRootFixed {
    right: 14px !important;
    bottom: calc(var(--m-nav-h) + var(--m-nav-pad) + 14px) !important;
    /* GLOBAL RULING (Josh, 2026-08-02): Donna floats ABOVE the pull-up
       sheet on every tab — top layer, bottom-right, always tappable.
       Sheet is 46, top bar/nav 48 — Donna outranks them all. */
    z-index: 60 !important;
  }
  /* the emerald FAB, restated at m-shell strength: paper.css's day round
     paints this button translucent white (its 0.55 wash was the halo in the
     day review shot) and outranks app.css's body-prefixed rule */
  body.m-shell #threadBadgeRootFixed .message-alert-button {
    background: var(--t-action) !important; color: var(--t-action-ink) !important;
    border: 0 !important; box-shadow: 0 6px 22px rgba(0, 0, 0, 0.32) !important;
  }
  body.m-shell #threadBadgeRootFixed .review-bell {
    /* stroke AND color: the glyph fills from currentColor, and paper.css
       paints .review-bell green with !important — both must flip to ink */
    stroke: var(--t-action-ink) !important; color: var(--t-action-ink) !important;
  }
  body.m-shell #threadBadgeRootFixed .badge-dot {
    background: var(--t-action-ink) !important; border-color: var(--t-action) !important;
  }
  body.m-shell #overview .dash-stats-strip {
    bottom: calc(var(--m-nav-h) + var(--m-nav-pad) + 14px) !important;
    right: 88px !important;
  }
  body.m-shell #buildStamp {
    bottom: calc(var(--m-nav-h) + var(--m-nav-pad) + 2px) !important;
    right: 80px !important;   /* clear of the FAB */
  }

  /* ---- the tabs' own top toolbars stand down where the pill/chips replace
     them. display:none keeps every control in the DOM — the mobile chips
     PROXY these buttons' clicks, so behavior stays one path. -------------- */
  body.m-shell #cold .cold-search-label { display: none !important; }
  body.m-shell #matrix .matrix-search-input { display: none !important; }
  /* the WHOLE toolbar strip retires on the phone (Josh's one-line ruling):
     its + and scoreboard now live in the chips line up top, proxied — the
     hidden DOM keeps computing and keeps taking the clicks */
  body.m-shell #cold .cold-toolbar { display: none !important; }
  body.m-shell #cold .cold-message:empty { display: none !important; }   /* no dead band where the toolbar was */
  /* SHEET TABS pinned under the chips (Josh: "sticky so I can see them at
     the top whenever I'm scrolling") — the strip leaves the list's bottom
     and rides fixed; #cold's content padding makes room below */
  body.m-shell #cold .cold-list-strip {
    position: fixed !important;
    top: calc(var(--m-top) + var(--m-pill-h) + 8px + var(--m-chip-h) + 8px);
    left: 0; right: 0; bottom: auto !important; z-index: 47;
    height: 48px; max-height: 48px; overflow-y: hidden;
    display: flex; gap: 8px; align-items: center;
    overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none;
    padding: 6px var(--m-x) 8px;
    background: var(--p-canvas);
    border-bottom: 1px solid var(--p-hair);
    margin: 0 !important;
  }
  body.night-mode.m-shell #cold .cold-list-strip { background: #060607; }
  /* the + never scrolls out of the strip (Josh: "has to be seen… it can
     move all the way to the right but no more") */
  body.m-shell #cold .cold-list-tabs { display: flex; align-items: center; gap: 8px; }
  body.m-shell #cold .cold-list-tabs [data-open-upload] {
    position: sticky; right: 0; z-index: 1;
    background: var(--p-canvas);
    box-shadow: -8px 0 8px var(--p-canvas);
  }
  body.night-mode.m-shell #cold .cold-list-tabs [data-open-upload] { background: #060607; box-shadow: -8px 0 8px #060607; }
  body.m-shell #cold .cold-list-strip::-webkit-scrollbar { display: none; }
  body.m-shell.m-has-chips #appView main > section.page#cold {
    padding-top: calc(var(--m-top) + var(--m-pill-h) + 8px + var(--m-chip-h) + 8px + 56px) !important;
  }

  /* ---- ACCOUNTS in the PROSPECT grammar (Josh's unification) -----------
     The bottom leads ledger RETIRED (redesign 2026-08-02): person/book
     filters live in "The book" sheet; the list clears the sheet peek. */
  body.m-shell #appView main > section.page#matrix {
    padding-bottom: calc(var(--m-nav-h) + var(--m-nav-pad) + var(--m-sheet-peek) + 16px) !important;
  }
  /* the book chips inside the sheet (manager/admin only) */
  .m-sheet-books {
    display: flex; gap: 8px; align-items: center;
    overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none;
    padding: 2px 0 12px;
  }
  .m-sheet-books::-webkit-scrollbar { display: none; }
  .m-sheet-books .m-lead {
    flex: 0 0 auto;
    height: 34px; padding: 0 14px;
    border: 1px solid var(--p-hair); border-radius: 10px;
    background: transparent; color: var(--p-ink-soft);
    font-size: 0.82rem; font-weight: 600; white-space: nowrap;
    cursor: pointer;
  }
  .m-sheet-books .m-lead.active {
    background: var(--m-wash-hi); color: var(--p-ink);
    border-color: var(--p-hair-hi);
  }
  /* account NAME: white and prominent like Prospects — never link-blue */
  body.m-shell #matrix .mc-name {
    color: var(--p-ink) !important;
    font-weight: 650 !important;
    text-decoration: none !important;
  }
  /* type parity with prospects is FONT parity — the prospect phone's tall
     tap padding belongs to its own two-line column and mangled this card's
     lines (round 4's second find) */
  body.m-shell #matrix .mc-phone { padding: 0 !important; }
  body.m-shell #matrix .mc-line2 { margin-top: 6px; }
  /* the right cluster: star + the colorful tappable status ---------------- */
  body.m-shell #matrix .mc-right {
    flex: 0 0 auto;
    display: inline-flex; align-items: center; gap: 3px;   /* star hugs the status (Josh) */
  }
  /* MINI GROUP HEADERS (Josh, 2026-08-02 round 2): just bold white text,
     tight height — the colored pill, the count badge, and the dark chevron
     box all stand down. The whole line still taps to collapse. */
  /* ROUND 4 (Josh): ONE full-bleed hairline above each group title — the
     inset stub line came from header borders living inside the padded td.
     The group's last card drops its own border so the lines never double;
     the title band pulls tight. */
  body.m-shell #matrix .acct-group { border: 0 !important; }
  body.m-shell #matrix .acct-group-head {
    border-top: 1px solid var(--p-hair) !important;
    background: transparent !important;
  }
  body.m-shell #matrix .acct-group:first-child .acct-group-head { border-top: 0 !important; }
  body.m-shell #matrix .acct-group .matrix-mcard:last-child { border-bottom: 0 !important; }
  body.m-shell #appView #matrix .acct-group-head td {
    /* DOUBLE-ID ON PURPOSE (the shoebox scar shape): a first-column rule
       with heavier specificity kept this td 30x44 in its card coat — the
       ghost square behind every header survived two lighter resets */
    display: block !important;
    width: 100% !important; max-width: 100% !important; min-width: 0 !important;
    height: auto !important; min-height: 0 !important;
    padding: 7px 16px 0 !important;
    background: transparent !important; border: 0 !important;
    box-shadow: none !important; border-radius: 0 !important;
  }
  body.m-shell #matrix .acct-group-toggle {
    background: transparent !important; border: 0 !important;
    box-shadow: none !important; padding: 0 !important; margin: 0 !important;
    display: flex; align-items: baseline; gap: 7px;
    width: auto !important; min-height: 0 !important;
  }
  body.m-shell #matrix .acct-group-chevron { display: none !important; }
  body.m-shell #matrix .acct-group-head .acct-group-pill {
    background: transparent !important; border: 0 !important;
    padding: 0 !important;
    color: var(--p-ink) !important;
    font-size: 0.88rem !important; font-weight: 700 !important;
    letter-spacing: 0 !important; text-transform: none !important;
  }
  body.m-shell #matrix .acct-group-count { font-size: 0.72rem; color: var(--p-ink-faint); }
  body.m-shell #matrix .mc-star {
    width: 34px; height: 34px; margin: -7px -4px -7px 0;
    display: inline-flex; align-items: center; justify-content: center;
    border: 0; background: transparent; padding: 0;
    font-size: 1.15rem; line-height: 1;
    color: var(--p-ink-faint); cursor: pointer;
  }
  body.m-shell #matrix .mc-star.on { color: var(--m-link); }
  body.m-shell #matrix .mc-stage-wrap { position: relative; display: inline-flex; }
  body.m-shell #matrix .mc-stage-face {
    font-size: 0.66rem;
    padding: 3px 9px !important;   /* smaller than the group pill's own coat */
    pointer-events: none;   /* the invisible select takes the tap */
  }
  body.m-shell #matrix .mc-stage-select {
    position: absolute; inset: 0;
    opacity: 0; border: 0;
    width: 100%; height: 100%;
    font-size: 16px;          /* iOS focus-zoom floor */
    cursor: pointer;
  }
  /* the old plain-text stage retired with the face */
  body.m-shell #matrix .mc-stage { display: none !important; }
  /* the toolbar box retires (the + proxies through the chips row) */
  body.m-shell #matrix .matrix-toolbar { display: none !important; }
  /* the account CARD (shares the prospect classes for one look).
     TABLE->BLOCK is the load-bearing reset: #cold got it in the phone-cards
     era, #matrix never did — flex/block children inside a live display:table
     was the mangled-rows root cause. */
  body.m-shell #matrix .table-wrap table,
  body.m-shell #matrix .table-wrap table tbody,
  body.m-shell #matrix .acct-group,
  body.m-shell #matrix .acct-group-head,
  body.m-shell #matrix .acct-group-head td { display: block !important; width: 100% !important; }
  body.m-shell #matrix table thead { display: none !important; }
  body.m-shell #matrix .matrix-mcard {
    display: block; position: relative !important;
    overflow: hidden;
    padding: 18px 16px !important;   /* the prospect row rhythm exactly */
    border-bottom: 1px solid var(--p-hair) !important;
    /* HEIGHT AUTO IS LOAD-BEARING (round 4 fix): a legacy rule pins tr
       height to 72px — the prospect-size type made content taller and the
       fixed height CLIPPED every card (Josh: "buttons are getting cut
       off"; probe showed height:72 vs content ~102) */
    height: auto !important; max-height: none !important;
    min-height: 72px;
    background: transparent !important;
  }
  body.m-shell #matrix .matrix-mcard td:not(.mcard-td) { display: none !important; }
  body.m-shell #matrix .matrix-mcard input[type=checkbox] { display: none !important; }
  body.m-shell #matrix .matrix-mcard .mcard-td {
    /* width 100% is THE fix of the whole mangled-rows saga: a first-column
       (checkbox) width rule capped this td at 30px and everything inside
       overflowed a shoebox */
    display: block; width: 100% !important; max-width: 100% !important;
    padding: 0 !important; border: 0 !important;
    background: transparent !important;
  }
  body.m-shell #matrix .mc-name {
    background: transparent; border: 0; padding: 0; text-align: left;
    cursor: pointer;
  }
  /* FLEX rows, no absolutes — a mid-refresh DOM hiccup once re-anchored
     absolute children across rows (the mangled-first-card shot); normal
     flow cannot cross-paint */
  body.m-shell #matrix .mc-line1 {
    display: flex; align-items: baseline; gap: 10px;
  }
  body.m-shell #matrix .mc-line1 .cold-name-row { flex: 1 1 auto; min-width: 0; }
  body.m-shell #matrix .mc-phone {
    flex: 0 0 auto;
    font-size: 0.88rem !important; font-weight: 500;
    font-variant-numeric: tabular-nums; white-space: nowrap;
    color: var(--p-ink) !important; text-decoration: none !important;
  }
  body.m-shell #matrix .mc-line2 {
    display: flex; align-items: baseline; gap: 10px; margin-top: 3px;
  }
  body.m-shell #matrix .mc-line2 .cold-context-line { flex: 1 1 auto; min-width: 0; margin: 0; }
  body.m-shell #matrix .mc-stage {
    flex: 0 0 auto;
    font-size: 0.8rem; font-weight: 600; color: var(--p-ink-soft);
    white-space: nowrap; max-width: 150px; overflow: hidden; text-overflow: ellipsis;
  }
  /* slim stage-group heads, sheet-section style */
  body.m-shell #matrix .acct-group-head td { background: transparent !important; padding: 12px 16px 4px !important; }

  /* the page's own big title is redundant under the tab bar's label */
  body.m-shell #matrix .workspace-head,
  body.m-shell #cold .workspace-head { display: none !important; }
  /* the Donna dial cluster leaves mobile Accounts (Josh: "don't need
     those") — the dial still lives on desktop and in Settings */
  body.m-shell #matrix .matrix-donna-dial { display: none !important; }

  /* ---- PROSPECT CARD RENDER PASS (Josh's on-device review, 2026-08-01):
     every card renders IDENTICALLY. The grey boxes bleeding through the
     Caliche card were the table's per-status td tints and field washes
     painting through the block-layout phone cards — desktop row grammar
     leaking into card grammar. On the phone, status lives in the status
     control's own color; the card surface is one clean plane. ------------ */
  body.m-shell #cold .cold-table tbody tr,
  body.m-shell #cold .cold-table tbody tr:hover,
  body.m-shell #cold .cold-table tbody td {
    background: transparent !important;
  }
  body.m-shell #cold .cold-table .cold-name-input,
  body.m-shell #cold .cold-table .cold-company-input,
  body.m-shell #cold .cold-table .cold-place-input,
  body.m-shell #cold .cold-table .cold-phone-cell input {
    background: transparent !important; border-color: transparent !important;
  }
  /* FLAT LIST (Josh's final-polish ruling, 2026-08-01: "content and
     dividers, not nested boxes"): the outer panel box and per-row chrome
     are GONE — the list sits on the page ground, rows separated by thin
     dividers, generous vertical padding carrying the air the boxes used to. */
  body.m-shell #cold .panel {
    background: transparent !important;
    border: 0 !important; box-shadow: none !important;
    border-radius: 0 !important;
    padding: 0 !important;
  }
  body.m-shell #cold .table-wrap {
    background: transparent !important;
    border: 0 !important; box-shadow: none !important;
  }
  body.m-shell #cold .cold-table, body.m-shell #cold .cold-table tbody,
  body.m-shell #cold .cold-table thead, body.m-shell #cold .cold-list-strip,
  body.m-shell #cold .cold-table-footer,
  body.m-shell #matrix .table-wrap, body.m-shell #matrix table,
  body.m-shell #matrix table tbody {
    background: transparent !important;
    box-shadow: none !important;
  }
  body.m-shell #matrix .panel, body.m-shell #tasks .panel,
  body.m-shell #matrix .table-wrap.matrix-grid,
  body.m-shell #matrix .account-directory,
  body.m-shell #matrix .acct-group {
    background: transparent !important;
    border: 0 !important; box-shadow: none !important; border-radius: 0 !important;
  }
  body.night-mode.m-shell #matrix .cold-table td,
  body.night-mode.m-shell #matrix table td,
  body.night-mode.m-shell #matrix table th {
    background: transparent !important;
  }
  body.m-shell #cold .cold-table tbody tr {
    padding: 18px 16px !important;
    border-bottom: 1px solid var(--p-hair) !important;
  }
  body.m-shell #cold .cold-table tbody tr:last-child { border-bottom: 0 !important; }
  body.m-shell #cold .cold-name-read,
  body.m-shell #matrix .mc-name {
    /* PROPORTION RULE (Josh, 2026-08-02 round 3): account names read at
       EXACTLY the prospect size — one rule, both tabs */
    font-size: 1.04rem; font-weight: 700; line-height: 1.25;
    color: var(--p-ink);
    /* ONE line (Josh): word-drop happens in the renderer; this ellipsis is
       only the fallback for a single unbreakable long word */
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    max-width: 100%;
  }
  /* promoted rows: the name IS the link to the account — button reset, same
     type, a quiet trailing arrow as the tell (no underline, his rule) */
  body.m-shell #cold .cold-name-link {
    display: inline-flex; align-items: baseline; gap: 6px;
    background: transparent; border: 0; padding: 0; text-align: left;
    cursor: pointer;
  }
  /* promoted names: no arrow — the HIGHLIGHT says tappable (his ruling) */
  body.m-shell #cold .cold-name-link { color: var(--m-link); }
  body.m-shell #cold .cold-name-link:active { opacity: 0.6; }
  body.m-shell #cold .cold-moved-link { display: none !important; }   /* the pill's job moved into the name */
  /* the wrapper is a column-flex whose child was sizing to intrinsic text
     width and sailing past the cell (probe: td 152, line 230) — pin BOTH */
  body.m-shell #cold .cold-table td:nth-child(2) .cold-identity-cell {
    width: 100% !important; max-width: 100% !important; min-width: 0 !important;
    overflow: hidden;
  }
  body.m-shell #cold .cold-context-line {
    display: block;
    width: 100% !important; max-width: 100% !important; min-width: 0 !important;
    font-size: 0.8rem; line-height: 1.35; color: var(--p-ink-soft);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  body.m-shell #cold .cold-context-line i { font-style: normal; opacity: 0.45; padding: 0 1px; }
  body.m-shell #cold .cold-table td:nth-child(2) { margin-top: 3px !important; }
  body.m-shell #cold .cold-table td:nth-child(4) { margin-top: 9px !important; }
  body.m-shell #cold .cold-table td:nth-child(5) { margin-top: 8px !important; }
  /* re-balance after the circle's removal: the number sits in the header
     row beside the name; the card's only circle left is note-send.
     td height AUTO is load-bearing — a legacy fixed 44px cell height let
     the name+contact stack overflow and the next line rendered over it
     (the collapsed-lines probe, 2026-08-01). */
  body.m-shell #cold .cold-table td { height: auto !important; min-height: 0 !important; }
  /* only the NAME row reserves room for the number; the context line runs
     the full card width beneath it */
  body.m-shell #cold .cold-table td:nth-child(1) { margin-right: 150px !important; }
  body.m-shell #cold .cold-table td:nth-child(2) { margin-right: 0 !important; }
  /* the NUMBER anchors to the CARD, not its table cell — a legacy 30px
     offset inside the flex cell kept shoving the digits off the edge (the
     clipped-last-digit probe). display:contents removes the wrapper from
     layout; the tr (position:relative) is the containing block. */
  body.m-shell #cold .cold-table td:nth-child(3) {
    position: static !important; width: auto !important; margin: 0 !important;
  }
  body.m-shell #cold .cold-phone-cell { display: contents !important; }
  body.m-shell #cold .cold-table .cold-phone-tap,
  body.m-shell #cold .cold-phone-cell input {
    /* RIGHT-anchored column (Josh round 11): the number's END is the shared
       edge — the status chevron below lines up with it exactly */
    position: absolute; top: 6px; right: 16px; left: auto;
  }
  body.m-shell #cold .cold-phone-cell input { width: 130px !important; text-align: right; }
  /* hierarchy: the company NAME leads the card */
  body.m-shell #cold .cold-name-input {
    font-size: 1.08rem !important; font-weight: 700 !important;
  }
  /* one note field, every card — promoted rows carried a differently-skinned
     input than fresh rows (the bordered-vs-bare mismatch in Josh's shot).
     Double-id on purpose: paper's invisible-until-touched cell fields use
     td-scoped :not() chains that out-rank anything weaker. */
  /* flat note field: a filled wash, no third box (final-polish item 1+5).
     Long notes keep the caret in view via the input's native horizontal
     scroll; nothing sits over the field (FAB clearance below). */
  body.m-shell #appView #cold .cold-table .cold-note-box input.cold-notes {
    background: var(--m-wash) !important;
    border: 0 !important;
    border-radius: 11px !important;
    padding: 9px 12px !important;
    opacity: 1 !important;
    min-width: 0; flex: 1 1 auto;
  }
  body.m-shell #cold .cold-note-send {
    width: 36px !important; height: 36px !important; min-height: 36px !important;
  }
  /* STATUS lives in the RIGHT column, small, directly under the number
     (Josh, 2026-08-01) — the note row rides up on the left. Label+chevron
     stay one tight control (width comes INLINE from mobile-shell, sized to
     the chosen value; an !important width here would beat that). */
  body.m-shell #cold .cold-table td:nth-child(4) {
    /* top 41 puts the status text on the CONTEXT line's baseline (name row
       is ~21px + 3px gap under 18px card padding) — his alignment ruling */
    position: absolute !important; top: 40px !important;
    right: 16px !important; left: auto !important;
    margin: 0 !important; width: auto !important; max-width: 170px;
    /* the cell's box must never eat taps meant for what's under it (the
       note-send interception the guard caught) — children re-enable */
    pointer-events: none;
  }
  body.m-shell #cold .cold-table td:nth-child(4) * { pointer-events: none; }
  body.m-shell #cold .cold-table td:nth-child(4) select,
  body.m-shell #cold .cold-table td:nth-child(4) button { pointer-events: auto; }
  body.m-shell #cold .cold-status-stack {
    /* status + date on ONE line ("Left Voicemail · Jul 30") — the date
       stacked below was colliding with the note band (Josh's fix #2) */
    flex-direction: row !important; align-items: center !important;
    justify-content: flex-end !important;
    gap: 7px !important;
  }
  /* the STATUS FACE: plain text, flush right at the number's end; the real
     select lies invisible on top as the tap target (per-label iOS padding
     made width math ragged — Josh's screenshot) */
  body.m-shell #cold .cold-status-wrap {
    position: relative; display: block;
  }
  body.m-shell #cold .cold-status-face {
    display: block; text-align: right;
    font-size: 0.8rem; font-weight: 600;
    color: var(--p-ink); white-space: nowrap;
    padding: 3px 0;
  }
  body.m-shell #cold .cold-status-wrap .cold-status-select {
    position: absolute !important; inset: 0 !important;
    width: 100% !important; height: 100% !important;
    opacity: 0 !important;
    appearance: none !important; -webkit-appearance: none !important;
    min-width: 0 !important; margin: 0 !important; padding: 0 !important;
    border: 0 !important;
  }
  /* semantic status colors on the face (mirrors the select's b- palette) */
  body.m-shell #cold .cold-status-face.b-interested,
  body.m-shell #cold .cold-status-face.b-trial { color: #34a373; }
  body.m-shell #cold .cold-status-face.b-needs-info { color: #e0932e; }
  body.m-shell #cold .cold-status-face.b-callback { color: #e0a94a; }
  body.m-shell #cold .cold-status-face.b-not-interested,
  body.m-shell #cold .cold-status-face.b-bad-number,
  body.m-shell #cold .cold-status-face.b-not-relevant { color: #e5533d; }
  body.m-shell #cold .cold-status-face.b-dormant { color: #b3a6f0; }
  body.m-shell #cold .cold-last-contact { display: none !important; }   /* moved beside the name */
  .cold-name-row { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
  .cold-name-date {
    flex: 0 0 auto;
    font-size: 0.7rem; color: var(--p-ink-faint);
    font-variant-numeric: tabular-nums; white-space: nowrap;
  }
  /* the left column now runs name → context → (note when opened) */
  body.m-shell #cold .cold-table td:nth-child(5) { margin-top: 8px !important; margin-right: 0 !important; }
  /* headroom for the right column: number + status on the context line */
  body.m-shell #cold .cold-table tbody tr { min-height: 88px; }
  body.m-shell #cold .cold-table td:nth-child(2) { margin-right: 168px !important; }
  /* the note SLIDES down when the card is tapped (no arrow — his ruling).
     CRITICAL (Josh's on-device fix #1): the open note is its OWN full-width
     row BELOW the status band — text can never run under the date or the
     send button, and the textarea WRAPS and grows with the note. */
  body.m-shell #cold tr.note-open td:nth-child(5) { margin-top: 16px !important; }
  body.m-shell #cold tr.note-open td:nth-child(4) { top: 40px !important; }
  body.m-shell #cold .cold-note-box {
    animation: m-note-in 0.18s ease;
    display: flex; align-items: flex-end; gap: 8px;
    width: 100%;
  }
  body.m-shell #appView #cold .cold-table .cold-note-box textarea.cold-notes {
    flex: 1 1 auto; min-width: 0;
    background: var(--m-wash) !important;
    border: 0 !important; border-radius: 12px !important;
    padding: 10px 12px !important;
    font-size: 16px !important; line-height: 1.4 !important;
    color: var(--p-ink) !important;
    resize: none; overflow-y: auto;
    min-height: 42px; max-height: 160px;
    white-space: pre-wrap; overflow-wrap: break-word;
  }
  @keyframes m-note-in {
    from { opacity: 0; transform: translateY(-6px); }
    to { opacity: 1; transform: none; }
  }
  @media (prefers-reduced-motion: reduce) { body.m-shell #cold .cold-note-box { animation: none; } }
  /* the 0/25 hero never clips (item 6): the chips FADE OUT under it instead
     of hard-cutting — the pill reads as its own right-aligned element */
  #mobileTopBar .m-chips {
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 18px), transparent);
    mask-image: linear-gradient(to right, #000 calc(100% - 18px), transparent);
  }
  #mobileTopBar .m-score { margin-left: 2px; z-index: 1; }
  /* the Donna FAB never covers a note field (item 7): the list keeps a
     FAB-sized runway at the bottom, and focusing any note lifts the FAB
     clear of the row being typed in */
  body.m-shell #appView main > section.page#cold {
    padding-bottom: calc(var(--m-nav-h) + var(--m-nav-pad) + 96px) !important;
  }
  body.m-shell:has(#cold .cold-note-box input:focus) #threadBadgeRootFixed {
    transform: translateY(-84px);
    transition: transform 0.2s ease;
  }

  /* ---- ACTIVITY: the task-first list (Josh's redesign, 2026-08-01 — no
     calendar grid, no Day/Week/Month toggle on the phone; Overdue / Today /
     Upcoming IS the time view; same flat-black grammar as Prospects). ----- */
  body.m-shell #tasks .workspace-head { display: none !important; }   /* the momentum sheet carries the day's numbers */
  body.m-shell #appView main > section.page#tasks {
    padding-left: 0 !important; padding-right: 0 !important;
  }
  body.m-shell.m-sheet-tasks #appView main > section.page#tasks {
    padding-bottom: calc(var(--m-nav-h) + var(--m-nav-pad) + var(--m-sheet-peek) + 16px) !important;
  }
  body.m-shell #tasks .premeeting-strip { margin: 0 var(--m-x); }
  .m-act-triage {
    display: flex; align-items: center; gap: 12px;
    width: calc(100% - 2 * var(--m-x));
    margin: 4px var(--m-x) 10px; padding: 14px 16px;
    border: 1px solid var(--p-hair-hi); border-radius: var(--m-radius);
    background: var(--m-wash); color: var(--p-ink);
    text-align: left; cursor: pointer;
  }
  .m-act-triage:active { background: var(--m-wash-hi); }
  .m-act-triage-main { display: flex; flex-direction: column; gap: 2px; flex: 1 1 auto; }
  .m-act-triage-main strong { font-size: 0.95rem; font-weight: 700; color: var(--t-bad); }
  .m-act-triage-main span { font-size: 0.8rem; color: var(--p-ink-soft); }
  .m-act-triage-go { font-size: 1.5rem; line-height: 1; color: var(--p-ink-faint); }
  .m-sheet-triage { width: 100%; margin: 12px 0 0; }
  .m-act-group {
    display: flex; align-items: baseline; gap: 8px;
    padding: 18px var(--m-x) 6px;
    font-size: 0.72rem; font-weight: 700;
    letter-spacing: 0.08em; text-transform: uppercase;
    color: var(--p-ink-soft);
  }
  .m-act-group em { font-style: normal; font-weight: 650; color: var(--p-ink-faint); }
  .m-act-row {
    display: flex; align-items: flex-start; gap: 12px;
    padding: 14px var(--m-x);
    border-bottom: 1px solid var(--p-hair);
  }
  .m-act-check {
    flex: 0 0 auto; width: 26px; height: 26px; margin-top: 1px;
    border: 1.6px solid var(--p-hair-hi); border-radius: 50%;
    background: transparent; cursor: pointer;
    position: relative;
  }
  .m-act-check::after { content: ''; position: absolute; inset: -9px; }   /* 44px thumb target */
  .m-act-check:active { background: var(--m-wash-hi); }
  .m-act-dot { flex: 0 0 auto; width: 8px; height: 8px; margin: 9px 9px 0; border-radius: 50%; background: var(--p-ink-faint); }
  .m-act-dot.done { background: var(--m-brand); }
  .m-act-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
  .m-act-title { font-size: 0.95rem; font-weight: 620; line-height: 1.3; color: var(--p-ink); }
  .m-act-sub { font-size: 0.8rem; color: var(--p-ink-soft); }
  .m-act-when { font-style: normal; color: var(--p-ink-faint); }
  .m-act-row.overdue .m-act-when { color: var(--t-bad); font-weight: 650; }
  .m-act-row.logged .m-act-title { font-weight: 500; color: var(--p-ink-soft); }
  .m-act-row.act-completing { opacity: 0.45; }
  /* the tap ANSWERS instantly (Josh: "not sure how the buttons work") —
     the circle fills with a check the moment it's hit */
  .m-act-row.act-completing .m-act-check {
    background: var(--m-brand); border-color: var(--m-brand);
  }
  .m-act-row.act-completing .m-act-check::before {
    content: '✓'; position: absolute; inset: 0;
    display: flex; align-items: center; justify-content: center;
    color: #fff; font-size: 0.85rem; font-weight: 700;
  }
  /* ---- THE ATTEMPT LOGGER: row button + flat action sheet -------------- */
  .m-log-btn {
    flex: 0 0 auto;
    width: 34px; height: 34px; padding: 7px;
    display: inline-flex; align-items: center; justify-content: center;
    border: 0; border-radius: 50%;
    background: transparent; color: var(--p-ink-faint);
    cursor: pointer;
  }
  .m-log-btn svg { width: 100%; height: 100%; }
  .m-log-btn:active { background: var(--m-wash); color: var(--p-ink); }
  body.m-shell #cold .cold-status-stack .m-log-btn { margin-top: 2px; pointer-events: auto; }
  #mLogSheet, #mBriefReply { position: fixed; inset: 0; z-index: 70; }
  #mLogSheet .m-log-scrim,
  #mBriefReply .m-log-scrim { position: absolute; inset: 0; background: rgba(0, 0, 0, 0.45); }
  #mLogSheet .m-log-panel,
  #mBriefReply .m-log-panel {
    position: absolute; left: 0; right: 0; bottom: 0;
    padding: 14px var(--m-x) calc(var(--m-nav-pad) + 10px);
    border-radius: var(--m-radius) var(--m-radius) 0 0;
    background: var(--p-card);
  }
  body.night-mode #mLogSheet .m-log-panel,
  #mBriefReply .m-log-panel { background: #0e0e10; }
  #mLogSheet .m-log-title,
  #mBriefReply .m-log-title {
    margin: 2px 4px 10px; font-size: 0.95rem; font-weight: 700; color: var(--p-ink);
  }
  #mLogSheet .m-log-row,
  #mBriefReply .m-log-row {
    display: block; width: 100%; text-align: left;
    padding: 14px 4px;
    border: 0; border-bottom: 1px solid var(--p-hair);
    background: transparent; color: var(--p-ink);
    font-size: 0.95rem; font-weight: 600; cursor: pointer;
  }
  #mLogSheet .m-log-row,
  #mBriefReply .m-log-row:active { background: var(--m-wash); }
  #mLogSheet .m-log-cancel,
  #mBriefReply .m-log-cancel { border-bottom: 0; color: var(--p-ink-soft); text-align: center; }
  .m-act-x {
    flex: 0 0 auto; width: 34px; height: 34px; margin: -6px -8px 0 0;
    border: 0; background: transparent; color: var(--p-ink-faint);
    font-size: 0.85rem; cursor: pointer;
  }
  .m-act-fold {
    display: block; width: 100%; text-align: left;
    padding: 14px var(--m-x);
    border: 0; border-bottom: 1px solid var(--p-hair);
    background: transparent; color: var(--p-ink-soft);
    font-size: 0.85rem; font-weight: 600; cursor: pointer;
  }
  .m-act-fold:active { background: var(--m-wash); }
  .m-act-empty { padding: 24px var(--m-x); font-size: 0.9rem; color: var(--p-ink-soft); }
  .m-act-add { display: flex; flex-wrap: wrap; gap: 8px; padding: 4px var(--m-x) 12px; }
  .m-act-add select, .m-act-add input {
    flex: 1 1 100%; height: 44px; padding: 0 12px;
    font-size: 16px;   /* the iOS focus-zoom floor */
    background: var(--m-wash); border: 1px solid var(--p-hair); border-radius: 12px;
    color: var(--p-ink);
  }
  .m-act-add button { height: 40px; padding: 0 18px; border-radius: var(--m-round); }
  .m-act-add .message { flex: 1 1 100%; margin: 0; }

  /* ---- 2026 recolor, page-control overrides (m-shell scope only): the
     remaining green CONTROLS go ink; semantic status colors stay ---------- */
  /* SUBTRACTION PASS (Josh, 2026-08-01): the call circle is gone on the
     phone — the NUMBER is the tap target. Thumb-sized hit area, quiet
     tappable affordance, taps log nothing. */
  body.m-shell #cold .tel-call-btn { display: none !important; }
  /* the number: COLOR signals tappable (Josh: "lose the underline") — the
     muted brand green, right-aligned on the NAME's baseline, hit area via
     padding not a floating box */
  body.m-shell #cold .cold-table .cold-phone-tap,
  body.m-shell #matrix .mc-phone {
    display: inline-flex; align-items: center;
    padding: 12px 0 12px 12px;
    font-size: 0.88rem !important; font-weight: 600;
    font-variant-numeric: tabular-nums; white-space: nowrap;
    color: var(--p-ink);            /* white like the rest — "too much color" (Josh) */
    text-decoration: none;
  }
  body.m-shell #cold .cold-table .cold-phone-tap:active { opacity: 0.6; }
  body.m-shell .cold-note-send { background: var(--t-action) !important; color: var(--t-action-ink) !important; border-color: transparent !important; }
  body.m-shell .cold-scoreboard { border-color: var(--p-hair-hi); background: var(--m-wash); }
  body.m-shell .cold-scoreboard strong { color: var(--p-ink); text-shadow: none; }
  body.m-shell .cold-score-bar b { background: var(--p-ink); }
  body.m-shell .cold-scoreboard.goal-hit { border-color: var(--p-ink); box-shadow: none; }
  body.m-shell .cold-moved-link, body.m-shell .cold-donna-file {
    background: var(--m-wash); color: var(--p-ink);
  }
  body.m-shell .cold-moved-link:hover, body.m-shell .cold-donna-file:hover { background: var(--m-wash-hi); }

  /* ---- THE PULL-UP STORY SHEET, HOME "TODAY" (stage (b) slice 1 — the
     "Local vibe" grammar): a rounded sheet peeking above the bottom nav,
     drag or tap to raise. Content is READ-LAYER truth only — real tasks,
     real dates, real accounts; empty sections say so plainly. ------------- */
  #mobileSheet {
    position: fixed;
    left: 0; right: 0;
    bottom: calc(var(--m-nav-h) + var(--m-nav-pad));
    top: calc(var(--m-top) + var(--m-pill-h) + 14px);
    z-index: 46;                 /* over the map, under top bar & nav taps */
    background: var(--p-card);
    border-radius: var(--m-radius) var(--m-radius) 0 0;
    box-shadow: 0 -8px 30px rgba(0, 0, 0, 0.22);
    transform: translateY(calc(100% - var(--m-sheet-peek)));
    transition: transform 0.26s cubic-bezier(0.32, 0.72, 0.28, 1);
    display: flex; flex-direction: column;
  }
  body.night-mode #mobileSheet { background: #0e0e10; box-shadow: 0 -8px 30px rgba(0, 0, 0, 0.5); }
  /* tabs WITH a chips row (Activity): the raised sheet stops below the
     chips, not under them — the headline was hiding behind the chip row */
  body.m-has-chips #mobileSheet {
    top: calc(var(--m-top) + var(--m-pill-h) + 8px + var(--m-chip-h) + 14px);
  }
  /* HOME's chips ride lower (below the map pill) — the sheet stops below
     THEM, or the chip row eats the raised peek's close tap */
  body.m-sheet-home #mobileSheet {
    top: calc(var(--m-top) + var(--m-pill-h) + 10px + var(--m-chip-h) + 16px);
  }
  #mobileSheet.open { transform: translateY(0); }
  #mobileSheet.dragging { transition: none; }
  @media (prefers-reduced-motion: reduce) { #mobileSheet { transition: none; } }
  #mobileSheet .m-sheet-peek {
    touch-action: none;   /* drag lives HERE — the body pans and scrolls freely
                             (the book's people chips wouldn't scroll, Josh) */
    flex: 0 0 auto;
    height: var(--m-sheet-peek);
    display: flex; flex-direction: column; align-items: center;
    gap: 3px; padding-top: 7px;
    cursor: grab;
  }
  #mobileSheet .m-sheet-handle {
    width: 38px; height: 4px; border-radius: 2px;
    background: var(--p-ink-faint); opacity: 0.55;
  }
  #mobileSheet .m-sheet-headline {
    display: flex; align-items: baseline; gap: 10px;
    width: 100%; padding: 2px var(--m-x) 0 16px;
  }
  #mobileSheet .m-sheet-headline h2 {
    margin: 0; font-size: 1.25rem; font-weight: 750; color: var(--p-ink);
  }
  #mobileSheet .m-sheet-headline span { font-size: 0.82rem; color: var(--p-ink-soft); }
  #mobileSheet .m-sheet-body {
    flex: 1 1 auto; min-height: 0;
    overflow-y: auto; -webkit-overflow-scrolling: touch;
    padding: 4px 16px calc(env(safe-area-inset-bottom, 0px) + 20px);
    touch-action: pan-y;
  }
  #mobileSheet:not(.open) .m-sheet-body { overflow-y: hidden; }
  .m-sheet-stats {
    display: flex; gap: 8px; overflow-x: auto;
    margin: 8px calc(-1 * var(--m-x)) 4px; padding: 2px var(--m-x) 6px;
    scrollbar-width: none;
  }
  .m-sheet-stats::-webkit-scrollbar { display: none; }
  .m-sheet-stat {
    flex: 0 0 auto;
    display: flex; flex-direction: column; gap: 1px;
    min-width: 92px;
    padding: 10px 14px;
    background: var(--m-wash); border-radius: var(--m-radius);
  }
  .m-sheet-stat strong { font-size: 1.25rem; font-weight: 750; color: var(--p-ink); font-variant-numeric: tabular-nums; }
  .m-sheet-stat span { font-size: 0.72rem; color: var(--p-ink-soft); white-space: nowrap; }
  /* the SYNTHESIS paragraph — the sheet's voice (grounded template prose) */
  .m-sheet-story {
    margin: 10px 2px 2px;
    font-size: 0.95rem; line-height: 1.55;
    color: var(--p-ink);
  }
  /* horizontal card rows — the story-sheet card grammar */
  .m-sheet-cardrow {
    display: flex; gap: 10px;
    overflow-x: auto; -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    margin: 0 calc(-1 * var(--m-x)); padding: 2px var(--m-x) 6px;
  }
  .m-sheet-cardrow::-webkit-scrollbar { display: none; }
  .m-sheet-card {
    flex: 0 0 auto;
    display: flex; flex-direction: column; gap: 3px;
    width: 172px;
    padding: 12px 13px;
    border: 0; border-radius: var(--m-radius);
    background: var(--m-wash);
    text-align: left; cursor: pointer;
  }
  .m-sheet-card:active { background: var(--m-wash-hi); }
  .m-sheet-card strong {
    font-size: 0.88rem; font-weight: 650; color: var(--p-ink);
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden; line-height: 1.3;
  }
  .m-sheet-card span {
    font-size: 0.74rem; color: var(--p-ink-soft);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .m-sheet-card em { font-style: normal; font-size: 0.72rem; color: var(--p-ink-faint); }
  .m-sheet-card.overdue em { color: var(--t-bad); font-weight: 650; }

  /* imported note substance ("Alt address: …") stays one quiet clamped
     line in the list; the full text lives on the record (title shows it) */
  body.m-shell #cold .cold-note-display { display: none !important; }   /* Josh: "shouldn't be showing up" — record keeps it */
  body.m-shell #cold tr.note-open .cold-note-display {
    display: -webkit-box !important; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
    overflow: hidden; font-size: 0.76rem; color: var(--p-ink-faint);
  }

  .m-sheet-section { margin-top: 16px; }
  .m-sheet-section-head {
    display: flex; align-items: center; gap: 8px;
    margin-bottom: 6px;
    font-size: 0.74rem; font-weight: 700; letter-spacing: 0.09em;
    text-transform: uppercase; color: var(--p-ink-faint);
  }
  .m-sheet-section-head svg { width: 16px; height: 16px; }
  .m-sheet-row {
    width: 100%;
    display: flex; align-items: center; gap: 10px;
    padding: 11px 12px;
    border: 0; text-align: left; cursor: pointer;
    background: transparent; border-radius: 12px;
    border-bottom: 1px solid var(--p-hair);
  }
  .m-sheet-row:last-child { border-bottom: 0; }
  .m-sheet-row:active { background: var(--m-wash); }
  .m-sheet-row .m-sheet-row-main {
    flex: 1 1 auto; min-width: 0;
    display: flex; flex-direction: column; gap: 1px;
  }
  .m-sheet-row .m-sheet-row-main strong {
    font-size: 0.94rem; font-weight: 600; color: var(--p-ink);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .m-sheet-row .m-sheet-row-main span {
    font-size: 0.78rem; color: var(--p-ink-soft);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .m-sheet-row .m-sheet-when {
    flex: 0 0 auto; font-size: 0.74rem; font-variant-numeric: tabular-nums;
    color: var(--p-ink-faint); white-space: nowrap;
  }
  .m-sheet-row.overdue .m-sheet-when { color: var(--t-bad); font-weight: 650; }
  /* ---- THE BRIEF's framing layer: quotes are visually SET APART so a
     chosen quote never reads as a data claim (the hard line) -------------- */
  .m-brief-quote {
    margin: 4px 0 10px; padding: 2px 0 2px 14px;
    border-left: 2px solid var(--p-hair-hi);
  }
  .m-brief-quote p {
    margin: 0; font-style: italic; font-size: 0.95rem; line-height: 1.5;
    color: var(--p-ink);
  }
  .m-brief-quote cite {
    display: block; margin-top: 3px;
    font-style: normal; font-size: 0.75rem; color: var(--p-ink-faint);
  }
  .m-brief-grit {
    margin: 0 0 12px; font-size: 0.88rem; font-weight: 650;
    letter-spacing: 0.01em; color: var(--p-ink-soft);
  }
  .m-brief-strong {
    margin: 10px 0 2px; font-size: 0.92rem; font-weight: 700;
    color: var(--p-ink);
  }
  /* the daily devotional (Josh's morning review): verse then the word —
     framing content, set apart from the grounded story below it */
  .m-brief-devotional { margin: 2px 0 14px; }
  .m-brief-divider { border: 0; border-top: 1px solid var(--p-hair); margin: 14px 0; }
  .m-brief-reply {
    display: inline-block; width: auto;
    margin: 12px 0 2px; padding: 8px 20px;
    border: 1px solid var(--p-hair-hi); border-radius: var(--m-round);
    background: transparent; color: var(--p-ink);
    font-size: 0.85rem; font-weight: 650;
    cursor: pointer;
  }
  .m-brief-reply:active { background: var(--m-wash); }
  .m-brief-word {
    margin: 8px 0 0; font-size: 0.92rem; line-height: 1.55;
    color: var(--p-ink);
  }
  /* ---- THE DESIGNED BRIEF (part 2): rhythm from eyebrows + thin accent
     hairlines, never boxes. Green = forward, amber = cleanup. ------------- */
  .m-brief-sec { margin: 0 0 16px; padding-left: 12px; border-left: 2px solid var(--p-hair); }
  .m-brief-fwd { border-left-color: rgba(63, 174, 125, 0.55); }
  .m-brief-cleanup { border-left-color: rgba(222, 170, 80, 0.45); }
  .m-brief-hero { border-left-color: var(--m-brand); }
  .m-brief-eyebrow {
    margin: 0 0 4px; font-size: 0.68rem; font-weight: 700;
    letter-spacing: 0.09em; text-transform: uppercase;
    color: var(--p-ink-soft);
  }
  .m-brief-hero .m-brief-eyebrow { color: var(--m-brand); }
  .m-brief-hero-line { margin: 0; font-size: 1.02rem; line-height: 1.5; font-weight: 600; color: var(--p-ink); }
  .m-brief-line {
    display: block; width: 100%; text-align: left;
    margin: 0 0 6px; padding: 0; border: 0; background: transparent;
    font-size: 0.9rem; line-height: 1.5; color: var(--p-ink);
  }
  .m-brief-cleanup .m-brief-line { font-size: 0.85rem; color: var(--p-ink-soft); }
  .m-brief-triage { cursor: pointer; text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--p-hair-hi); }
  .m-brief-name { color: var(--m-link); text-decoration: none; font-weight: 650; }
  .m-reply-text, .m-reply-name {
    width: 100%; margin: 0 0 10px; padding: 11px 12px;
    font-size: 16px;   /* iOS focus-zoom floor */
    background: var(--m-wash); border: 1px solid var(--p-hair); border-radius: 12px;
    color: var(--p-ink);
  }
  .m-reply-text { min-height: 96px; }
  /* Donna's folded morning items */
  .m-brief-donna-greet { font-weight: 650; }
  .m-brief-donna-head {
    margin: 10px 0 2px; font-size: 0.72rem; font-weight: 700;
    letter-spacing: 0.08em; text-transform: uppercase;
    color: var(--p-ink-soft);
  }
  .m-brief-donna-line {
    margin: 4px 0; font-size: 0.88rem; line-height: 1.5;
    color: var(--p-ink);
  }
  .m-brief-donna-line .thread-link { color: var(--m-link); text-decoration: none; }
  /* THE MOVEMENT DIGEST — clean prose blocks, hairline-separated, no boxes */
  .m-move-item {
    padding: 12px 0;
    border-bottom: 1px solid var(--p-hair);
    cursor: pointer;
  }
  .m-move-item:last-child { border-bottom: 0; }
  .m-move-head {
    display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  }
  .m-move-head strong { font-size: 0.95rem; font-weight: 700; color: var(--p-ink); }
  .m-move-head span { font-size: 0.75rem; color: var(--p-ink-faint); }
  .m-move-item p {
    margin: 5px 0 0; font-size: 0.88rem; line-height: 1.5;
    color: var(--p-ink);
  }
  .m-move-item .m-move-next { color: var(--p-ink-soft); font-weight: 600; }
  .m-move-empty { padding: 14px 0; font-size: 0.88rem; color: var(--p-ink-soft); }
  /* the phone's quick-add row */
  .m-acct-add { display: flex; flex-wrap: wrap; gap: 8px; padding: 4px var(--m-x) 14px; }
  .m-acct-add input, .m-acct-add textarea {
    flex: 1 1 100%; padding: 11px 12px;
    font-size: 16px;   /* the iOS focus-zoom floor */
    background: var(--m-wash); border: 1px solid var(--p-hair); border-radius: 12px;
    color: var(--p-ink);
  }
  .m-acct-add textarea { min-height: 74px; }
  .m-acct-add-actions { display: flex; gap: 8px; }
  .m-acct-add .message { flex: 1 1 100%; margin: 0; }
  .m-sheet-empty {
    padding: 10px 12px; font-size: 0.85rem; color: var(--p-ink-faint);
  }
  .m-sheet-more { padding: 6px 12px 0; font-size: 0.78rem; color: var(--p-ink-faint); }
  /* stats strip retires on Home — its numbers live in the sheet now */
  body.m-shell #overview .dash-stats-strip { display: none !important; }
  /* the FAB sits at the SAME bottom-right spot on every page (Josh: it may
     overlap the sheet peek — consistency wins) */
  body.donna-sheet-open #mobileSheet, body:has(#donnaDock.open) #mobileSheet { display: none !important; }

  /* ---- PROFILE & SETTINGS (Josh's banking-app reference, 2026-08-01):
     the page owns its header — back chevron, Sign out, big title, identity
     row, then stacked expandable cards. No floating top bar here. --------- */
  body.m-shell #appView main > section.page#userProfile {
    padding-top: calc(env(safe-area-inset-top, 0px) + 8px) !important;
  }
  .mprof { display: flex; flex-direction: column; gap: 4px; }
  .mprof-topline {
    display: flex; align-items: center; justify-content: space-between;
    min-height: 44px;
  }
  .mprof-back {
    width: 44px; height: 44px; margin-left: -10px;
    display: inline-flex; align-items: center; justify-content: center;
    border: 0; background: transparent; color: var(--p-ink);
    cursor: pointer; padding: 0;
  }
  .mprof-back svg { width: 26px; height: 26px; }
  .mprof-signout {
    border: 0; background: transparent; padding: 10px 2px;
    color: var(--p-ink); font-size: 1rem; font-weight: 650;
    text-decoration: underline; text-underline-offset: 3px;
    cursor: pointer;
  }
  .mprof-title {
    margin: 2px 0 14px;
    font-size: 2.05rem; font-weight: 750; letter-spacing: -0.02em;
    color: var(--p-ink);
  }
  .mprof-id {
    display: flex; align-items: center; gap: 14px;
    padding-bottom: 18px;
  }
  .mprof-avatar {
    width: 62px; height: 62px; flex: 0 0 auto;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%;
    background: var(--m-wash); color: var(--p-ink);
    font-size: 1.3rem; font-weight: 750;
  }
  .mprof-id-meta { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
  .mprof-id-meta strong { font-size: 1.05rem; color: var(--p-ink); }
  .mprof-id-meta span {
    font-size: 0.85rem; color: var(--p-ink-soft);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  /* FLAT rows on the one black, hairline dividers — the prospect look
     (Josh: "less boxes"); each row navigates to its own page */
  .mprof-cards { display: flex; flex-direction: column; gap: 0; }
  .mprof-row {
    width: 100%; display: flex; align-items: center; gap: 14px;
    padding: 18px 4px;
    border: 0; border-bottom: 1px solid var(--p-hair);
    background: transparent; cursor: pointer; text-align: left;
    color: var(--p-ink);
  }
  .mprof-row:last-child { border-bottom: 0; }
  .mprof-row:active { background: var(--m-wash); }
  .mprof-go {
    width: 18px; height: 18px; flex: 0 0 auto;
    color: var(--p-ink-faint);
  }
  .mprof-page-body { padding-top: 4px; }
  .mprof-page-body * { max-width: 100%; min-width: 0; box-sizing: border-box; }
  .mprof-page-body table { display: block; overflow-x: auto; }
  .mprof-card-icon {
    display: inline-flex; width: 23px; height: 23px; flex: 0 0 auto;
    color: var(--p-ink-soft);
  }
  .mprof-card-icon svg { width: 100%; height: 100%; }
  .mprof-card-label { flex: 1 1 auto; font-size: 1.05rem; font-weight: 650; }
  .mprof-chev {
    width: 20px; height: 20px; flex: 0 0 auto;
    color: var(--p-ink-faint);
    transition: transform 0.18s ease;
  }
  .mprof-card.open .mprof-chev { transform: rotate(180deg); }
  .mprof-card.open .mprof-card-icon { color: var(--p-ink); }
  .mprof-card-body {
    padding: 0 16px 16px;
    border-top: 1px solid var(--p-hair);
    padding-top: 14px;
  }
  /* the desktop sections keep their own inner markup — cap anything wide */
  .mprof-card-body * { max-width: 100%; min-width: 0; box-sizing: border-box; }
  .mprof-card-body table { display: block; overflow-x: auto; }
  @media (prefers-reduced-motion: reduce) { .mprof-chev { transition: none; } }
}

@media (max-width: 640px) {
  /* the wide-screen extra never appears on the phone — the card keeps its
     exact compact grammar (Josh's rule: mobile is untouched) */
  body.m-shell #matrix .mc-extra { display: none !important; }
  body.m-shell #matrix .mc-main { display: block; width: 100%; }
}

@media (max-width: 640px) {
  /* the desktop's "Log" word never shows on the phone (icon only) */
  body.m-shell .m-log-btn .mc-log-word { display: none !important; }
}
