/* ---------------------------------------------------------------------
   Mobile shell -- phone-only (<=640px) chrome layer.
   mobile-shell-build-plan.md §6 Stage 1 (scaffold). Loaded last in index.html's <head> (after
   tokens.css, components.css, shell.css, pages.css) so its rules win at equal specificity without
   needing !important. Every rule below is either unconditional-but-inert (display:none at all
   widths) or gated behind the 640px query, so desktop/tablet stay pixel-identical to today.

   The tab bar drives/reflects the existing router (js/modules/navigation.js) through
   js/modules/mobile-shell.js -- it is not a second router. #sidebar / #sidebarOverlay /
   #hamburgerBtn stay in the DOM at every width (navigation.js looks them up unguarded); this
   file only ever hides them visually on phones, never removes them.
   --------------------------------------------------------------------- */

.tabbar { display: none; }
/* Phone-only elements that calculators insert into the page unconditionally: hidden at every
   width by default so they never leak onto desktop; each is revealed only inside the <=640px
   block below (.tabbar above, .result-strip / .detail-link here). */
.result-strip { display: none; }

@media (max-width: 640px) {
  /* No way to reach the sidebar's own opener on a phone -- the bottom tab bar replaces it as the
     primary navigation surface. #sidebar/#sidebarOverlay stay in the DOM (untouched here) for the
     router's unguarded lookups; they simply have no opener left to reveal them. */
  .hamburger { display: none; }

  .tabbar {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    /* box-sizing is border-box globally (tokens.css), so the safe-area inset must be ADDED to the
       height, not left to eat into the fixed 64px. Without this, an installed iOS PWA's home-indicator
       inset (~34px) shrinks the tabs' content box and crams the icons against the top edge. Adding it
       keeps a full 64px content row above the inset, so the icons stay vertically centered. */
    height: calc(64px + env(safe-area-inset-bottom));
    padding-bottom: env(safe-area-inset-bottom);
    background: color-mix(in oklab, var(--surface-card) 88%, transparent);
    backdrop-filter: saturate(1.4) blur(14px);
    -webkit-backdrop-filter: saturate(1.4) blur(14px);
    border-top: 1px solid var(--border-subtle);
    /* Below the quick-switcher overlay (60) and its own dialog stack, above ordinary page
       content. The sidebar/overlay are unreachable on phone (no opener left, see .hamburger
       above), so there is no drawer-open state left to out-rank. */
    z-index: 40;
  }

  .tab {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    background: none;
    border: 0;
    cursor: pointer;
    font-family: inherit;
    color: var(--ink-muted);
    padding: 0;
  }
  .tab .tlabel { font-size: 10.5px; font-weight: 600; letter-spacing: .01em; }
  .tab[aria-current="page"] { color: var(--primary); }
  .tab[aria-current="page"] .tlabel { font-weight: 700; }
  /* Non-color active cue (WCAG 1.4.1) -- a short accent bar at the tab's top
     edge, additional to (not a replacement for) the color/weight change above. */
  .tab[aria-current="page"]::before {
    content: "";
    position: absolute;
    top: 0;
    left: 50%;
    transform: translateX(-50%);
    width: 22px;
    height: 2.5px;
    border-radius: var(--r-full);
    background: var(--primary);
  }

  /* Page content clears the fixed tab bar. .wrap is the scroll content's only padded container
     (the document itself scrolls -- there is no separate overflow:auto region), so this is the
     correct element to pad rather than .app-main or body. */
  .wrap { padding-bottom: calc(64px + env(safe-area-inset-bottom) + 16px); }
}

/* ---------------------------------------------------------------------
   Result sheet (build-plan §5/§6 Stage 2A) -- peek -> expandable sheet -> full nutrient detail.
   This is an evolution of js/modules/mobile-result-dock.js's headline dock, not a new component:
   the dock still only OBSERVES already-rendered result DOM (see that file's header comment), and
   these are purely the classes it (and Stage 3's per-calculator modules) mount into. Three
   families are defined here, all phone-gated:
     1. The sheet itself -- .sheet/.sheet-peek/.sheet-grab/.peek-metric/.sheet-body/.res-line/
        .detail-btn/.scrim -- pattern (a) metric calculators (tube feeds, goal volume, regimen,
        GIR, micronutrient screen, PN worksheet, estimated needs, chylothorax).
     2. .result-strip -- the slim inline green summary for pattern (c) artifact calculators
        (advancement plan, recipes, growth, corrected age) that have no per-kg metric and no sheet.
     3. .nutri-row -- full-detail nutrient rows, parity with desktop's detailed view (non-negotiable
        §1.5), reused by both the sheet's "See full nutrient detail" target and pattern (b)'s
        "See nutrients of this mix" link.

   Colors map to the app's real dark-readout tokens (css/tokens.css): --readout-bg/-ink/-accent
   already back every dark "printout" panel (pre.readout, .renal-recipe-readout); --primary-tint/
   --primary-container/--on-primary-container are hex-identical to the mockup's --green-wash/
   --primary-tint/--on-primary-tint, so no new color was invented, only the real names substituted.

   The sheet's container keeps the existing "mobile-result-dock" class (so the build-plan's
   `.page:has(> .mobile-result-dock:not([hidden]))` scroll-reserve selectors in pages.css keep
   matching it) and additionally gains "sheet" only when the dock is constructed with `sheetRows`.
   Every layout rule below that must OUTRANK pages.css's plain `.mobile-result-dock:not([hidden])`
   grid layout (specificity 0,2,0) is written against the compound `.mobile-result-dock.sheet`
   (specificity 0,3,0 once combined with :not([hidden])) so it always wins regardless of the two
   files' load order -- this file never edits pages.css/shell.css to get there. Calculators that
   pass no sheetRows never gain "sheet", so they render exactly as they did before Stage 2A. */

:root {
  --tabbar-h: 64px; /* matches the literal already used by .tabbar's height, above */
  --peek-h: 66px;
}

@media (max-width: 640px) {
  .scrim {
    position: fixed;
    inset: 0;
    /* Modal over the tab bar (40) but below the quick-switcher overlay (60) --
       the dim must cover the whole viewport, including the tab bar, while the
       sheet is expanded. */
    z-index: 45;
    background: rgba(0, 0, 0, .34);
    opacity: 0;
    pointer-events: none;
    transition: opacity .22s ease-out;
  }
  .scrim.show { opacity: 1; pointer-events: auto; }
  @media (prefers-reduced-motion: reduce) {
    .scrim { transition: none; }
  }

  /* The sheet itself sits one above the scrim, still below the quick-switcher
     overlay (60). js/modules/mobile-shell.js toggles `mshell-sheet-open` on
     <body> when the sheet expands; make the (now-covered) tab bar untappable
     for the duration so it can't be reached from under the scrim/sheet. */
  body.mshell-sheet-open .tabbar { pointer-events: none; }

  .mobile-result-dock.sheet:not([hidden]) {
    display: flex;
    flex-direction: column;
    position: fixed;
    left: 0;
    right: 0;
    bottom: var(--tabbar-h);
    top: auto;
    z-index: 46;
    background: var(--readout-bg);
    color: var(--readout-ink);
    border-radius: var(--r-xl) var(--r-xl) 0 0;
    box-shadow: var(--shadow-raised);
    max-height: calc(100% - 90px);
    transform: translateY(calc(100% - var(--peek-h)));
    transition: transform .34s cubic-bezier(.22, 1, .36, 1);
  }
  .mobile-result-dock.sheet.open { transform: translateY(0); }
  @media (prefers-reduced-motion: reduce) {
    .mobile-result-dock.sheet:not([hidden]) { transition: none; }
  }

  .sheet-grab {
    position: absolute;
    top: 7px;
    left: 50%;
    transform: translateX(-50%);
    width: 40px;
    height: 5px;
    border-radius: var(--r-full);
    background: rgba(255, 255, 255, .42);
    border: 0;
    padding: 0;
    cursor: pointer;
  }
  .sheet-peek {
    display: flex;
    align-items: center;
    gap: 22px;
    height: var(--peek-h);
    box-sizing: border-box;
    padding: 17px 20px 9px;
    cursor: pointer;
  }
  .peek-metric { display: flex; flex-direction: column; gap: 1px; line-height: 1.08; min-width: 0; }
  .peek-metric .n {
    display: block;
    font-family: var(--font-mono);
    font-size: 18px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--readout-accent);
    /* Wrap rather than ellipsis-truncate: the peek is the ONLY always-visible result on a phone,
       so a clipped clinical number would be worse than a slightly taller peek. Matches the desktop
       dock's wrap-over-ellipsise choice (pages.css .mobile-result-dock-value/-label). */
    white-space: normal;
    overflow-wrap: anywhere;
  }
  .peek-metric .u { font-size: 10px; color: rgba(240, 241, 242, .72); letter-spacing: .02em; }

  .sheet-body { padding: 4px 18px 20px; overflow-y: auto; }
  .sheet-body h3 {
    font-size: 11px;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--readout-accent);
    margin: 14px 0 10px;
    font-weight: 700;
  }
  .res-line {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    padding: 9px 0;
    border-top: 1px solid rgba(255, 255, 255, .09);
    font-size: 14px;
  }
  .res-line:first-of-type { border-top: 0; }
  .res-line .rl { color: rgba(240, 241, 242, .82); }
  .res-line .rv { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-weight: 600; }

  .detail-btn {
    margin-top: 18px;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    height: 50px;
    padding: 0 16px;
    border-radius: var(--r-md);
    border: 1px solid rgba(255, 255, 255, .16);
    background: rgba(255, 255, 255, .06);
    color: var(--readout-ink);
    font-family: inherit;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
  }
  .detail-btn:hover { background: rgba(255, 255, 255, .11); }

  /* Pattern (c) -- inline slim summary strip for artifact calculators (schedules/recipes/growth/
     corrected age) with no per-kg metric and no sheet. Same green-wash family the rest of the app
     already uses for this treatment (css/pages.css .dash-whats-new, css/components.css .totals-card). */
  .result-strip {
    display: flex;
    align-items: baseline;
    gap: 10px;
    margin-top: 6px;
    padding: 15px 16px;
    border-radius: var(--r-lg);
    background: var(--primary-tint);
    border: 1px solid var(--primary-container);
  }
  .result-strip .rn {
    font-family: var(--font-mono);
    font-size: 22px;
    font-weight: 700;
    color: var(--on-primary-container);
    font-variant-numeric: tabular-nums;
  }
  .result-strip .rt {
    font-size: 13px;
    font-weight: 600;
    /* De-emphasized relative to .rn so the number reads as the focal point;
       stays on-brand (same token family) and holds >=4.5:1 on the green tint. */
    color: color-mix(in oklab, var(--on-primary-container) 72%, transparent);
    line-height: 1.3;
  }

  /* Full nutrient-detail rows -- parity with desktop's detailed view (non-negotiable §1.5). */
  .nutri-row { display: flex; align-items: baseline; gap: 12px; padding: 12px 16px; border-top: 1px solid var(--border-subtle); }
  .nutri-row:first-child { border-top: 0; }
  .nutri-name { flex: 1; font-size: 14px; }
  .nutri-val { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-weight: 600; font-size: 14px; }
  .nutri-dri { min-width: 54px; text-align: right; font-size: 11.5px; font-weight: 600; color: var(--ink-muted); font-variant-numeric: tabular-nums; }
  .nutri-dri.low { color: var(--danger); }
}

/* ---------------------------------------------------------------------
   Stage 2B (build-plan §3, §6 Stage 2) -- phone-only layout for the four
   hub/home pages: dashboard (Home), alltools (Calculators), referencehub
   (Reference), settings (Settings). These are EXISTING pages -- everything
   below restyles their existing markup (scoped by page id so no other page is
   touched); the only genuinely new markup is Home's "Jump to" hub tiles and
   "Quick Access" list (index.html, inside #mshellHomeQuick), both wrapped in
   .phone-only-block so they never render above 640px. Recent/Pinned/the
   workspace summary+growth-trend widgets/What's New/the search hero are hidden
   on phone rather than rebuilt for phone -- ruling §7.2, Recent+Pinned stay
   deferred and this never starts a recency store.

   Every new class here (.list/.row/.mshell-*) is unused anywhere else in the
   app today (grepped before adding), so nothing outside these four pages'
   phone layout is affected. Colors are the same real tokens used everywhere
   else in the app -- --surface-card/--border-subtle/--ink-muted/--primary-tint/
   --primary-container/--on-primary-container etc. from css/tokens.css -- no
   color is invented. Existing router-wired classes are reused for navigation
   (.hub-card[data-page], .tool-launch-card[data-page]) rather than inventing a
   new click path; .row/.list are purely visual and carry no click handling of
   their own. */

.phone-only-block { display: none; }

@media (max-width: 640px) {
  .phone-only-block { display: block; }

  /* Shared list/row primitives (mockup's .list/.row), used by Home's new Quick
     Access block. Names are new and otherwise unused in the app (see note
     above), so this is scoped to the phone breakpoint only out of the same
     file-discipline as the rest of this stylesheet, not because of a naming
     collision risk. */
  .list {
    background: var(--surface-card);
    border: 1px solid var(--border-subtle);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-card);
    overflow: hidden;
  }
  .row {
    display: flex;
    align-items: center;
    gap: 14px;
    width: 100%;
    text-align: left;
    cursor: pointer;
    font-family: inherit;
    color: var(--ink);
    background: transparent;
    border: 0;
    border-top: 1px solid var(--border-subtle);
    padding: 14px 16px;
    min-height: 56px;
  }
  .row:first-child { border-top: 0; }
  .row:active { background: var(--surface-low); }
  .row .rbody { flex: 1; min-width: 0; }
  .row .rtitle { display: block; font-size: 15px; font-weight: 600; letter-spacing: -.01em; color: var(--ink); }
  .row .rsub { display: block; font-size: 12.5px; color: var(--ink-muted); margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .row .chev { flex: 0 0 auto; width: 18px; height: 18px; color: var(--ink-faint); }
  .row .icon-chip { flex: 0 0 34px; height: 34px; width: 34px; }

  .mshell-section-label {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--ink-muted);
    margin: 22px 4px 10px;
  }
  .mshell-section-label:first-child { margin-top: 6px; }

  /* ---- Home (#page-dashboard) ----
     Ruled first cut: workspace strip (the existing global .patient-banner/
     .patient-tabs chrome -- untouched, already renders above every page) +
     first-run banner (existing #dashWorkspacePromo .feature-banner; already
     stacks to a phone-appropriate column via components.css's own 640px rule,
     so nothing new is needed for it here) + the Jump-to hubs and Quick Access
     built below. Everything else on today's Home is hidden on phone: the
     search hero (the topbar's own search icon already covers search at every
     width <=860px, see shell.css), the workspace-summary/growth-trend cards,
     Pinned, Recent, and What's New -- all explicitly outside the first-cut
     scope (§7.2). #dashPwaInstallPromo is deliberately left showing: it is not
     one of the deferred Recent/Pinned/What's-New items, and "install to home
     screen" matters most on the exact surface (a phone) this stage targets. */
  #page-dashboard .dash-search-hero,
  #page-dashboard .dash-workspace-section,
  #page-dashboard #dashboardPinnedSection,
  #page-dashboard #dashboardRecentSection,
  #page-dashboard .dash-whats-new {
    display: none;
  }

  #page-dashboard .mshell-hub-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
  }
  /* .hub-card/.hub-card-copy/-title/-desc are the same class the References hub
     already uses for its own card grid (components.css) -- reused here rather
     than inventing a parallel tile component. Scoped overrides below only
     compact it for the 2-up phone tile; the References hub's own use of
     .hub-card (a few sections down) gets a completely different, row-shaped
     override under its own #page-referencehub scope, so the two never fight. */
  #page-dashboard .mshell-hub-row .hub-card {
    min-height: 108px;
    gap: 22px;
    padding: 16px;
  }
  #page-dashboard .mshell-hub-row .hub-card-copy { gap: 3px; }
  #page-dashboard .mshell-hub-row .hub-card-title { font-size: 15px; }
  #page-dashboard .mshell-hub-row .hub-card-desc { font-size: 12px; }

  /* ---- Calculators (#page-alltools) ----
     #allToolsList / TOOL_SECTIONS (js/modules/tool-navigation.js) already is a
     "grouped calculator list" -- the mockup's s-calcs screen -- so nothing new
     is built here, only restyled: each .tool-tile-grid becomes one bordered
     list card and each .tool-tile loses its own card chrome for a flat,
     divided row, matching .list/.row above without introducing a second set of
     class names for the same look. */
  #page-alltools .all-tools-toolbar label[for="allToolsSearch"] {
    position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip: rect(0 0 0 0); white-space: nowrap; border: 0; padding: 0; margin: -1px;
  }
  #page-alltools #allToolsSearch {
    border-radius: var(--r-full);
    background: var(--surface-low);
  }
  #page-alltools .tool-section-heading,
  #page-referencehub .tool-section-heading {
    grid-template-columns: 1fr;
    font: 700 11px/16px var(--font-ui);
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--ink-muted);
  }
  #page-alltools .tool-section-heading .icon-chip,
  #page-alltools .tool-section-heading::after,
  #page-referencehub .tool-section-heading .icon-chip,
  #page-referencehub .tool-section-heading::after {
    display: none;
  }
  #page-alltools .tool-tile-grid {
    display: block;
    background: var(--surface-card);
    border: 1px solid var(--border-subtle);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-card);
    overflow: hidden;
  }
  #page-alltools .tool-tile {
    background: transparent;
    border: 0;
    border-top: 1px solid var(--border-subtle);
    border-radius: 0;
    box-shadow: none;
    min-height: 56px;
    flex-direction: row;
    align-items: center;
  }
  #page-alltools .tool-tile:first-child { border-top: 0; }
  #page-alltools .tool-tile:hover,
  #page-alltools .tool-tile:focus-within {
    transform: none;
    box-shadow: none;
    border-color: var(--border-subtle);
  }
  #page-alltools .tool-tile-main {
    flex-direction: row;
    align-items: center;
    padding: 12px 8px 12px 14px;
  }
  #page-alltools .tool-tile-main .body-sm { -webkit-line-clamp: 1; }
  #page-alltools .tool-tile-actions { position: static; opacity: 1; padding-right: 14px; }

  /* ---- Reference (#page-referencehub) ----
     Its own .hub-card-grid sections (js/modules/reference-hub.js) are the
     mockup's "Hubs" list -- converted the same way as Calculators' tiles
     above, into one bordered list card per section with divided rows. The
     .library-feature lead panel already stacks to a phone column via its own
     existing 640px rule in components.css, so it is left alone here. */
  #page-referencehub .hub-card-grid {
    display: block;
    background: var(--surface-card);
    border: 1px solid var(--border-subtle);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-card);
    overflow: hidden;
  }
  #page-referencehub .hub-card {
    display: flex;
    align-items: center;
    gap: 14px;
    min-height: 56px;
    border: 0;
    border-top: 1px solid var(--border-subtle);
    border-radius: 0;
    box-shadow: none;
    padding: 14px 16px;
  }
  #page-referencehub .hub-card:first-child { border-top: 0; }
  #page-referencehub .hub-card:hover { transform: none; box-shadow: none; }
  #page-referencehub .hub-card > .icon-chip { flex: 0 0 34px; height: 34px; width: 34px; }
  #page-referencehub .hub-card-copy { gap: 2px; }
  /* The inline "View DRI Tables ->" text-action reads as a second, redundant
     affordance once the whole row is already the tap target (mockup rows carry
     only a trailing chevron) -- hidden here rather than removed from the DOM. */
  #page-referencehub .hub-card .text-action { display: none; }

  /* ---- Settings (#page-settings) ----
     Its .shortcut-row rows (components.css) already divide with a border-top
     exactly like .row above -- restyled in place: each <section> becomes one
     .list-styled card and its .card-header becomes the section label above it,
     matching the mockup's grouped-switches layout without new markup. */
  #page-settings > section {
    padding: 0;
    margin-bottom: 24px;
    border: 0;
    box-shadow: none;
    background: transparent;
    max-width: none;
  }
  #page-settings > section > .card-header {
    padding: 0 4px 10px;
    font: 700 11px/16px var(--font-ui);
    letter-spacing: .06em;
    text-transform: uppercase;
  }
  #page-settings > section > .card-header .icon-chip { display: none; }
  #page-settings > section > .card-header h2 { font: inherit; color: var(--ink-muted); }
  #page-settings .settings-card {
    background: var(--surface-card);
    border: 1px solid var(--border-subtle);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-card);
    padding: 4px 16px;
  }
}

/* ---------------------------------------------------------------------
   Stage 3 pattern (b): "See nutrients of this mix" link -- a recipe that IS a
   feeding (Renal Blend, Blenderized) renders inline and links into its full
   nutrient detail. Light green affordance on the page surface (distinct from
   the dark .detail-btn used inside the result sheet). Phone-gated like the rest:
   display:none by default so the button never shows on desktop even if a
   calculator inserts it into the DOM unconditionally; only shown <=640px.
   --------------------------------------------------------------------- */
.detail-link { display: none; }
@media (max-width: 640px) {
  .detail-link {
    margin-top: 16px;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    min-height: 50px;
    padding: 12px 16px;
    border-radius: var(--r-md);
    border: 1px solid var(--primary-container);
    background: var(--primary-tint);
    color: var(--on-primary-container);
    font-family: inherit;
    font-size: 14px;
    font-weight: 700;
    text-align: left;
    cursor: pointer;
  }
  .detail-link:hover { filter: brightness(0.97); }
}

/* ---------------------------------------------------------------------
   Stage 3 pattern (b) progressive disclosure. A calculator marks its full
   nutrient-breakdown section `.mshell-collapsible`; the "See nutrients of this
   mix" link toggles `.is-revealed`. Collapse is a PURE CSS breakpoint: the rule
   exists only <=640px, so desktop is NEVER subject to it -- a resize across the
   breakpoint can never strand a hidden section on desktop (parity, plan §1.5).
   The class is applied unconditionally by JS; only this media query hides it.
   --------------------------------------------------------------------- */
@media (max-width: 640px) {
  .mshell-collapsible:not(.is-revealed) { display: none; }
}

/* ---------------------------------------------------------------------
   Stage 4: the search palette on phone. The header ⌕ button (#quickSwitcherBtn,
   shown <=860px) already opens the EXISTING quick-switcher (quick-switcher.js) --
   no second search is built. These phone-only rules just make that overlay feel
   native: a top-anchored near-full-width sheet, and a 16px input so iOS Safari
   does NOT auto-zoom on focus (any <16px input triggers the zoom). Desktop keeps
   the centered dialog (this block is <=640px only; mobile-shell.css loads last so
   these win at equal specificity over shell.css's base .qs-* rules).
   --------------------------------------------------------------------- */
@media (max-width: 640px) {
  .qs-overlay { padding-top: max(12px, env(safe-area-inset-top)); }
  .qs-dialog {
    width: calc(100vw - 20px);
    max-width: none;
    max-height: min(78vh, 620px);
  }
  .qs-input {
    font-size: 16px;
    padding: 16px;
    min-height: 52px;
  }
}

/* ---------------------------------------------------------------------
   Mockup-parity pass (mockup.html) on top of Stage 2B. Five phone-only
   changes, each scoped to the four hub pages / dashboard / #patientBanner:

   1. The in-page <header class="page-header"> (h1 + .page-subtitle) is hidden
      on the four hub/list pages -- the topbar already shows the page title on
      phone (body[data-page] is set by navigation.js), so the in-page duplicate
      is redundant and its stuck focus-outline (h1 tabindex="-1") goes with it.
      Calculator pages are explicitly out of scope this pass, so this is an
      allowlist of four ids, not a blanket ".page-header { display:none }".
   2. #page-alltools's "Browse calculators" card is flattened: its own
      .card-header (icon-chip + <h2>) is hidden and the section's card chrome
      stripped, so #allToolsSearch sits bare on the page background like the
      mockup's .searchbox. .tool-tile-grid/.tool-tile below (Stage 2B, above)
      already carry the list-card look, so nothing else here needs to change.
   3. The global workspace strip (#patientBanner) is restricted to Home. It is
      unconditionally hidden on every OTHER phone page via body[data-page] (set
      by navigation.js) rather than per-page-id selectors, so any current or
      future non-hub page is covered without another allowlist. Untouched at
      >640px.
   4. Calculators' rows show a trailing chevron instead of the pin action: the
      existing .tool-tile-actions (pin button, opacity:1'd static in Stage 2B
      above) is hidden here, and a CSS-drawn chevron is added via ::after on
      .tool-tile-main, matching the mockup's .row .chev glyph. Desktop keeps
      the real pin affordance untouched.
   5. #dashWorkspacePromo (the "create a workspace" feature-banner on Home) is
      recompacted from its desktop dark-hero treatment into the mockup's
      .ws-banner: a light green tint card with copy left / button right. Text
      is owned by a sibling change -- only layout/color here.
   --------------------------------------------------------------------- */

@media (max-width: 640px) {
  /* ---- 1. Redundant in-page header on the four hub/list pages ---- */
  #page-dashboard > .page-header,
  #page-alltools > .page-header,
  #page-referencehub > .page-header,
  #page-settings > .page-header {
    display: none;
  }

  /* ---- 2. Flatten the "Browse calculators" card on #page-alltools ---- */
  #page-alltools section:has(.all-tools-toolbar) {
    background: transparent;
    border: 0;
    box-shadow: none;
    padding: 0;
    margin: 0 0 24px;
  }
  #page-alltools section:has(.all-tools-toolbar) > .card-header {
    display: none;
  }

  /* ---- 3. Workspace strip is Home-only on phone ---- */
  body:not([data-page="dashboard"]) #patientBanner {
    display: none;
  }

  /* ---- 4. Rows show a chevron, not a pin action ---- */
  #page-alltools .tool-tile-actions {
    display: none;
  }
  #page-alltools .tool-tile-main {
    position: relative;
    padding-right: 30px;
  }
  #page-alltools .tool-tile-main::after {
    content: "";
    position: absolute;
    right: 10px;
    top: 50%;
    width: 8px;
    height: 8px;
    border: solid var(--ink-faint);
    border-width: 0 2px 2px 0;
    transform: translateY(-50%) rotate(-45deg);
  }

  /* ---- 5. Compact the Home workspace banner into the mockup's .ws-banner ---- */
  #page-dashboard #dashWorkspacePromo {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 6px 0 2px;
    padding: 13px 15px;
    border-radius: var(--r-lg);
    background: var(--primary-tint);
    border: 1px solid var(--primary-container);
    color: var(--on-primary-container);
    box-shadow: none;
  }
  #page-dashboard #dashWorkspacePromo .feature-banner-copy {
    align-items: center;
    gap: 10px;
  }
  #page-dashboard #dashWorkspacePromo .icon-chip {
    display: none;
  }
  #page-dashboard #dashWorkspacePromo h2 {
    font-size: 14px;
    font-weight: 700;
    color: inherit;
    margin: 0;
  }
  #page-dashboard #dashWorkspacePromo p {
    font-size: 12px;
    color: inherit;
    opacity: .9;
    margin: 2px 0 0;
  }
  #page-dashboard #dashWorkspacePromo .btn {
    flex: 0 0 auto;
    height: 40px;
    padding: 0 16px;
    border-radius: var(--r-full);
  }
}
