/* Production Ledger — MOBILE PASS (owner ask 2026-07-31).
 *
 * WHY THIS FILE EXISTS: there was no stylesheet shared by every page. app.css reaches only
 * app.html; every other page carries its own inline <style>. So the same handful of shared
 * controls — the feedback button, the theme toggle, the account avatar, the announcement close —
 * failed touch sizing independently on 10-19 pages each, with nowhere to fix them once. This is
 * that one place.
 *
 * THE RULE THIS FILE OBEYS: resize, don't squish. Nothing here makes anything smaller. Every rule
 * GROWS a control or a font so it works under a thumb.
 *
 * EVERYTHING is inside @media (pointer: coarse). That is a capability query, not a width query:
 * it matches touch input, so a desktop browser at a narrow window is completely unaffected and the
 * desktop layout cannot regress. It is the same convention app.css already established.
 *
 * MEASURED, not guessed. Every selector below failed a real headless audit at 320/375/390/430/768.
 * Re-run tests/mobile-viewport.test.cjs after touching this.
 */

@media (pointer: coarse) {

  /* ── 1. iOS ZOOM ────────────────────────────────────────────────────────────────────────────
   * Safari zooms the ENTIRE page when a focused input's font-size is under 16px, then leaves the
   * user zoomed in and scrolled sideways. It is invisible on desktop and infuriating on a phone.
   * Measured offenders ranged 12px to 15.2px across home, invoices, app, contracts, kit, calendar,
   * profile, me, login and landing. 16px is the exact threshold, not a preference. */
  /* !important is load-bearing here, not laziness: every page styles its own controls by ID
   * (#hm-period, #year-select, #labor-dept-pick...), which outranks any selector this shared file
   * can write. Verified safe before using it — the audit confirmed NO control on the site is
   * deliberately larger than 16px, so this can only ever grow text, never shrink it. Scoped to
   * coarse pointers, so desktop cannot be touched. */
  input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]),
  select,
  textarea {
    font-size: 16px !important;
  }

  /* A <select> is a control, not text. Same 44px floor as the buttons. */
  select { min-height: 44px; }

  /* Text fields were sized for FONT only in the first pass — 16px stopped the iOS zoom but left
   * boxes 36-42px tall. A field you have to hit precisely is the same failure as a small button,
   * and these are the controls someone fills in on a phone between setups. Every text input and
   * textarea now carries the same 44px floor. Excludes checkbox/radio (sized in §4), range and
   * file (native UI we must not stretch), and colour swatches. */
  input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]):not([type="color"]),
  textarea { min-height: 44px; }

  /* ── 2. SHARED CONTROLS ─────────────────────────────────────────────────────────────────────
   * These live on nearly every page and each failed independently. Sized by GROWING the control,
   * not by faking a hit area with a pseudo-element — several of these already use ::after for
   * their icon, and a transparent overlay would have clobbered it. */

  /* Feedback widget — 37x37 on 19 page-views, the most-repeated failure in the audit. */
  /* ⚠ THE FLOOR ALSO LIVES IN feedback-widget.js NOW (2026-08-22), and that is deliberate
   * duplication, not drift. This file is the widget's ONLY override point and stays the pinned
   * one — but it is a LINKED STYLESHEET, and a page that never links it got no floor at all: the
   * pill measured 37x37 at 390px on terms, privacy, refund and cookie-policy, all four of which
   * ship the widget and none of which ship this file. An allowlist that depends on every page
   * remembering to opt in omits by construction, the same way the account-button list above did.
   * So the widget carries its own `height: 44px` intrinsically at every width, and this line
   * stays as the belt-and-braces override. THE TWO MUST AGREE ON 44 — if that number ever moves,
   * move it in both. Neither is load-bearing alone, which is the point. */
  .plfb-btn { min-width: 44px; min-height: 44px; }

  /* Browse Equipment search clear — 20x20 by design on a mouse, where it sits inside the field
     and must not crowd the text. The hit area is grown without moving the glyph, the same
     transparent-::after trick app.css uses for .modal-close. */
  .drawer-search-clear { position: absolute; }
  .drawer-search-clear::after {
    content: '';
    position: absolute;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    width: 44px; height: 44px;
  }

  /* Light/dark toggle — 30x30 on 10 pages. */
  .fi-theme-btn { min-width: 44px; min-height: 44px; }

  /* Account avatar. Four different ids for the same control across five header variants; all 34x34.
   * If a new page introduces another header class, its button id belongs on this list. */
  /* ⚠ AND ONE OF THEM WAS MISSING FOR A YEAR (2026-08-22). The comment above says "five header
   * variants" and then lists four ids. kit.html's `.kv-user-btn` — declared `width: 34px;
   * height: 34px` — was never on it, so the Equipment page's account button stayed 34x34 under a
   * thumb while its four siblings were 44x44. Nothing failed; an allowlist omits by construction
   * and says nothing, the same way the money-privacy blur allowlist does. Measured 34x34 hit area
   * at 390 AND 768, both themes, before this line existed. min-width/min-height beat the declared
   * width/height per the used-value algorithm, so no !important is needed. */
  #pl-user-btn, #cr-user-btn, #rp-user-btn, #user-btn, #kv-user-btn,
  .pl-user-btn, .cr-user-btn, .rp-user-btn, .user-btn, .kv-user-btn { min-width: 44px; min-height: 44px; }

  /* Hamburger (plnav) — 80x34, wide enough but too short to hit reliably. */
  #pl-navmenu-btn, .pl-navmenu-btn, .mkt-burger { min-height: 44px; }

  /* Announcement dismiss — measured as small as 13x12 on crew and kit. The worst target on the
   * site: a 13px X that closes a banner covering content. */
  .announcement-banner-close { min-width: 44px; min-height: 44px; }

  /* Password reveal eye on the auth screens — 30x30, and the one control someone taps while
   * mistyping a password on a phone. */
  .pw-reveal-toggle { min-width: 44px; min-height: 44px; }

  /* "undo" on a paid deposit — 11px, zero padding, no height of its own. It is the control
     someone reaches for the moment they realise they marked the WRONG thing paid, which makes it
     the last one that should be hard to hit. Grown rather than faked with a ::after, because it
     sits inline in a sentence ("✓ Deposit paid — undo") where an overlay would cover the text
     beside it. inline-flex + align-items keeps it on the baseline of that sentence. */
  .btn-link-sm { min-height: 44px; display: inline-flex; align-items: center; }

  /* Logo / wordmark links. Measured 22x22 on 35 page-views — it is how you get Home from anywhere,
   * and it was the smallest persistent target after the shared controls. */
  /* min-WIDTH too: the re-audit measured these at 22x44 — the height fix landed, but a 22px-wide
   * strip is still a miss, and this is how you get Home from anywhere. */
  .fi-brand, .brand, .mkt-brand, .auth-brand, .rp-logo {
    min-width: 44px;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }

  /* Bulk-import-from-documents review table's per-row remove button (owner ask, 2026-08-16 mobile
     pass) — a bare "✕" icon button, easy to miss at its unstyled size once the row restacks into a
     full-width card (see the width-based restack rule in section 6 below). */
  .ext-docs-review-table .btn { min-width: 44px; min-height: 44px; }

  /* Page-specific controls the audit still caught after the shared pass. */
  .rt-btn, .gs-dismiss, .gs-step, .mini-badge, .role-info-btn,
  .cr-viewseg-btn, .auth-link, .promo-open { min-height: 44px; }

  /* Unfilled-slot card actions on the crew roster (That's me / Not needed / Add to crew). They
   * are pill-sized by design on desktop, so they need the floor declared here like every other
   * page-specific control — a new control is not exempt just because it is new. */
  .cr-ghost-foot button { min-height: 44px; min-width: 44px; }

  /* ── 2b. INSIDE THE POPUPS (owner 2026-07-31: "The popups and everything need to be adapted
   * for mobile and tablet") ────────────────────────────────────────────────────────────────
   * Everything above was measured on controls the page shows at rest. A closed overlay's
   * contents have a 0x0 rect, so the first audit SKIPPED them entirely and reported clean —
   * the feedback panel alone hid six failing controls on fourteen pages. These were measured
   * with every dropdown, drawer and modal forced open.
   *
   * FEEDBACK PANEL. Its CSS is injected from feedback-widget.js, so it cannot be edited in a
   * stylesheet — it has to be overridden here. This is the panel behind the button we already
   * sized: dismiss was 16x20, the tabs 155x37, the email field 316x38. */
  .plfb-x { min-width: 44px; min-height: 44px; }
  .plfb-tab, .plfb-send, .plfb-addphoto { min-height: 44px; }
  .plfb-email { min-height: 44px; }

  /* MODAL DISMISS. A 35x36 × in the corner of a signing or template dialog — the control
   * someone reaches for one-handed to get out of a modal they opened by accident. */
  /* (.modal-x removed 2026-08-16 — no such class anywhere; .ov-close/.sheet-close stay as the
   * redesign overlay vocabulary even though nothing emits them yet.) */
  .mclose, .ov-close, .sheet-close { min-width: 44px; min-height: 44px; }

  /* Contracts signature-mode tabs (Type / Draw) — how a signer picks how to sign. */
  .tab { min-height: 44px; }

  /* App header actions (Save / New / Recent / Share / Tracking / Duplicate / Appearance).
   * app.css pins `.header-actions .btn { min-height: 34px }`, which out-specifies the shared
   * `.btn` rule above — hence the matching selector here. mobile.css loads AFTER app.css, so
   * equal specificity resolves in this file's favour. */
  .header-actions .btn { min-height: 44px; }

  /* The incentive chip's own controls — 13x12 and 38x16, the smallest pair left on the site. */
  .incentive-chip-close { min-width: 44px; min-height: 44px; }
  .incentive-chip-details { min-height: 44px; }

  /* Marketing + auth nav links. Standalone navigation, not prose. */
  .lk, .auth-hide, .showcase-btn, .upc { min-height: 44px; display: inline-flex; align-items: center; }

  /* FOOTER + NAV LINK LISTS. A stacked column of policy and section links (Privacy, Terms,
   * Cookie Policy, Refund Policy, Features, Pricing, Kit catalog, Contact) measured 14-19px
   * tall with nothing between them — four legal links inside 64 vertical pixels is one
   * ambiguous target, not four. Scoped to real link LISTS and nav bars so running copy is
   * untouched: these are stacked navigation, never a target inside a sentence. */
  footer li > a, .footer-col li > a, .auth-footer-nav > a,
  nav > a, .mkt-nav > a {
    min-width: 44px;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }

  /* Standalone links that ARE the action of their block, not part of a sentence. A short word
   * like "Crew" fails on WIDTH once the height is fixed, so both floors are set. */
  .teaser-link, .muted-link, .kit-helper-crew-link {
    min-width: 44px;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }

  /* Pricing comparison category toggles — full-width rows that expand a feature section.
   * Wide enough already; they measured 39px tall. */
  tr.cat > td > button { min-height: 44px; }

  /* Home's to-do view switcher (Today / Week) and the activity category filters (All / …) —
   * segmented pill controls at 24-27px. */
  .tsegs button, .afilters button { min-width: 44px; min-height: 44px; }

  /* Pricing's fine-print legal row (Terms · Privacy) — 14px tall next to a price. */
  .foot a {
    min-width: 44px;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }

  /* The logged-out sync prompts on the tracker and the agreements bay. Each reads as a sentence
   * ("Log in to sync"), but each is the ONLY route to signing in from that surface, so it gets a
   * real target rather than the in-sentence exemption. */
  .iv-sync a, #sync-note a {
    min-width: 44px;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }

  /* The incentive chip's Details control failed on WIDTH once its height was fixed. */
  .incentive-chip-details { min-width: 44px; }

  /* Logo + accent pickers in the invoice editor. Excluded from the general input rule because
   * they are native file/colour widgets, but they are still controls someone taps on a phone —
   * 21px and 36px tall respectively. */
  #invoiceLogoUpload, #invoiceAccentOverride { min-height: 44px; }

  /* ── 2c. MISSES FROM THE 07-31 PASS (re-measured 2026-08-03) ────────────────────────────────
   * Ten controls the locked pass did not reach. Two kinds of miss: controls that got their HEIGHT
   * from the shared `.btn` rule and still fail on WIDTH, and the Finances v2 surface, which
   * postdated the tap audit entirely so none of it was ever measured. Same method as everything
   * above — measured at 390 and 768 with touch emulation, and grown, never shrunk. */

  /* Money-privacy toggle (the eye that hides amounts). Icon-only, so it clears 44 on height from
   * `.btn` and misses on width: 38x44 on home. Its Finances twin measures 48x44 today — floored
   * with it so the pair cannot drift apart on a copy-edit. */
  #hm-privacy-btn, #fin-privacy-btn { min-width: 44px; }

  /* Home. "Close out job" inside an open binder measured 232x33 — wide, and too short.
   * "Snooze" on a to-do row is a bare text button: 39x14, the smallest target left on the page.
   * The to-do checkbox `.tick` is 17x17 by declaration — it is the one control on Home you tap
   * every day, and it fails both floors. `.pacts .btn.xs` (the project-row actions) measured
   * 34x44: height already fixed, width still a miss. */
  .bo-close-job { min-height: 44px; }
  .snz { min-width: 44px; min-height: 44px; }
  .pacts .btn.xs { min-width: 44px; min-height: 44px; }
  /* `.tick` is the exception this file already carves out for checkboxes: a 17px box grown to
   * 44x44 renders as a large empty square with a 10px check floating in it (screenshot-verified —
   * it reads as broken, and a regression is not a fix). It has no ::after of its own, so it gets
   * the transparent hit-area extender instead — the same pattern app.css uses on coarse pointers,
   * and the one the tap audit measures as a real 44px target. The glyph box is untouched. */
  .tick { position: relative; }
  .tick::after { content: ''; position: absolute; top: -13px; right: -14px; bottom: -14px; left: -13px; }

  /* Finances v2 (invoices.html). Built after the tap pass, so it was never in the audit set:
   * `.f2-btn` measured 75x31 and every job-card action inherits that box, `.f2-close-job` 101x31,
   * the four page tabs 82x27. `#fin-new-from-empty` is the same `.f2-btn` shape in the empty
   * state, so it carries the same 31px height — floored by name so it cannot be missed again. */
  .f2-btn, .fin-tab, .f2-close-job, #fin-new-from-empty { min-height: 44px; }

  /* ICON BUTTONS — these failed on WIDTH, not height: a 28-34px square with a glyph in it. They
   * are dismissals, closes and steppers, i.e. the controls someone jabs at while holding a phone
   * one-handed. Square them off at 44 so the target matches the intent. */
  /* (dead-code sweep 2026-08-16: .plt-close/.plt-skip/.plt-nav removed — tour.js never used
   * those names; its real buttons are the bare `button.x/.skip/.nav` already in this list,
   * which is what has been carrying the tour's tap floor all along.) */
  .cal-tbtn, .avatar-upload-btn, .modal-close, .ctx-dismiss, .gs-dismiss,
  .mkt-burger, .rt-btn,
  button.x, button.skip, button.nav {
    min-width: 44px;
    min-height: 44px;
  }

  /* ── 2d. THE KIT BROWSE DRAWER (measured 2026-08-07) ─────────────────────────────────────────
   * The 07-31 lock names this surface as the one it could not reach: kit.html navigates
   * programmatically during an overlay pass and kills its own execution context, so the page was
   * audited AT REST and its drawer never opened. Measured now with the drawer forced open and CDP
   * touch emulation on: the add (+) and edit (✎) on every gear row came back 38x38 at phone width
   * and — worse — 24x24 and 22x22 on a TABLET, because kit.html's own sizing lives in a
   * `@media (max-width: 600px)` block that a 768px iPad never enters. 38 is close enough to look
   * fixed and small enough to miss; 22 is the desktop size showing through on a touch screen. Add-
   * to-kit is THE action of this drawer, the reason you opened it.
   * Overridden here, not in kit.html, because mobile.css is linked after that inline <style> and
   * these are the same specificity (0,1,0): document order is what decides. It also lands the rule
   * in a POINTER query instead of a width one, which is what makes the tablet case work. min-WIDTH
   * matters as much as height (a 38x44 button is still a miss), and min- rather than a fixed size
   * so the row keeps flexing — the name beside them is `.gear-row-info { flex: 1; min-width: 0 }`.
   * Measured after: 44x44 rect AND 44x44 hit area at both 390 and 768, no sideways scroll.
   * Pinned by tests/mobile-viewport, which measures this LIVE. */
  .gear-add-btn, .gear-edit-kit-btn { min-width: 44px; min-height: 44px; }
  /* The ✕ that removes a line from My Kit, sized with them for the same reason. */
  .kit-line-remove { min-width: 44px; min-height: 44px; }

  /* ── 2e. THE KIT SUB-HEADER, AND THE DRAWER'S OWN CHROME (measured 2026-08-22) ───────────────
   * §2d fixed the controls INSIDE the Browse drawer. It never measured the bar you drive the page
   * FROM, and every control on it failed: `.kv-back-btn` 39x23 (phone) / 112x28 (tablet), the three
   * `.kv-tier-btn` pills 26-27px tall at both widths, `.kv-user-btn` 34x34 (fixed in §2, where it
   * belonged all along). Identical in light and dark — these are geometry, not paint.
   *
   * WHY THE HEADER GETS TALLER, AND WHY THAT IS THE FIX: the owner was told plainly that honest
   * 44px targets grow the mobile Equipment header and said fix it. So every control here gets a
   * real min-height/min-width FLOOR, not a faked hit area.
   *
   * ⚠ NO TRANSPARENT ::after ON THIS SURFACE, DELIBERATELY. The tier pills are a segmented control
   * sitting shoulder to shoulder — 4px of flex gap inside a 3px-padded track. An ::after grown to
   * 44px would have each pill's hit area reaching ~19px into its neighbours', so a tap on the left
   * edge of "Advanced" would fire "Intermediate": a mis-tap is worse than a small target, and it
   * would be invisible to any audit that only measures each control alone. A min- FLOOR cannot do
   * that — flex lays real boxes out side by side, so hit areas physically cannot overlap. That is
   * also why the pills need no width work: they already measure 59/100/86px wide. The floor is
   * declared anyway so a shorter tier label can never reintroduce the miss.
   * The one control on this page that DOES need the ::after trick already has it: the search ✕ in
   * §2, which sits inside the field where a 44px box would crowd the text.
   *
   * Precedent for the pills: `.tsegs button, .afilters button` in §2b — Home's segmented switcher,
   * the same control shape, fixed the same way.
   * ⚠ These live HERE and not in kit.html for the reason §2d spells out: kit.html's own tap sizing
   * is in `@media (max-width: 600px)`, which a 768px iPad never enters, so a tablet gets raw
   * desktop sizes on a touch screen. A POINTER query covers both. mobile.css is linked after
   * kit.html's inline <style> (and pl-system.css, which loads last, sets none of these), so equal
   * specificity resolves in this file's favour. */
  .kv-back-btn, .kv-tier-btn { min-width: 44px; min-height: 44px; }

  /* The drawer's own chrome, missed by §2d the same way — it sized what the drawer CONTAINS, not
   * the drawer. `.drawer-close-btn` is the worst of them and the worst KIND of them: at ≤768px the
   * drawer is a full-screen sheet covering the header, so this ✕ is the only way back to the page,
   * and kit.html sizes it 40x40 inside that `max-width: 600px` block — meaning a tablet fell
   * through to the raw 28x28 desktop square. Exactly the §2d tablet bug, one element over.
   * `.drawer-tab` (the per-department tabs) measured 38px tall, `.drawer-more-btn` ("+ Sound",
   * "+ Grip"…) 40px on a phone and 26.5px on a tablet. */
  .drawer-close-btn { min-width: 44px; min-height: 44px; }
  .drawer-tab { min-height: 44px; }
  /* ⚠ SPECIFICITY, not order, is what beat the first version of this line. A bare
   * `.drawer-more-btn` (0,1,0) is out-ranked by kit.html's own `.drawer-more-btns button` (0,1,1)
   * inside its `max-width: 600px` block, so the phone kept 40px while the tablet — which never
   * enters that block — was fixed. It measured as a half-landed fix: green at 768, red at 390.
   * The matching selector is carried here for the same reason `.header-actions .btn` is in §2b. */
  .drawer-more-btn,
  .drawer-more-btns button, .drawer-more-btns .pill { min-height: 44px; }
  /* The per-row rate ("$350/day") is a DIV carrying data-action="edit-gear-rate" — tapping it
   * swaps in `.kit-rate-input`. A control the delegation treats as a button needs a button's
   * target; the input it becomes is already covered by the generic input floor in §1. */
  .gear-row-rate { min-height: 44px; display: flex; align-items: center; }
  /* The brand/family collapse rows ("▸ Sony (4)") inside an expanded gear group. kit.html already
   * decided these need a floor and set 40px / 36px — both short of 44, and both inside that same
   * `max-width: 600px` block, so a tablet fell through to the bare ~28px desktop row. The nested
   * selector is carried because `.brand-group-body .brand-group-head` (0,2,0) out-ranks the plain
   * one, the same specificity trap as `.drawer-more-btns button` above. */
  .brand-group-head,
  .brand-group-body .brand-group-head { min-height: 44px; }

  /* Checkbox LABELS carry the tap target. A native checkbox larger than ~22px looks broken, so the
   * box stays honest-sized and the label around it becomes the comfortable target instead. */
  label:has(> input[type="checkbox"]), label:has(> input[type="radio"]) {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    gap: 8px;
  }

  /* ── 3. BUTTONS AND MENU ITEMS ──────────────────────────────────────────────────────────────
   * The site's shared button classes measured 29-38px tall. 44px is the comfortable minimum.
   * min-height (not height) so a button whose content is already taller keeps its size. */
  .btn, .btn-primary, .btn-ghost, .auth-tab, .cb-btn, .cta, .mkt-cta,
  .cal-tbtn, .cal-today-btn, .cal-add-btn, .inq-submit, .subscribe-btn,
  .cr-viewseg-btn, .avatar-upload-btn, .tog, .ctx-dismiss {
    min-height: 44px;
  }
  /* Dropdown rows want a full-width comfortable strip, not a text-height sliver. */
  /* `.user-dropdown` added 2026-08-22: it is the ACCOUNT menu — the panel `.kv-user-btn` and its
   * four siblings above open — and it was the one dropdown vocabulary missing from this list.
   * Measured 35.5px tall per row (Account, Billing & plan, Contracts, Projects, Invoice…) at 390
   * and 768 in both themes. Same rule, same reason, and it lands on every page that ships this
   * panel rather than on kit.html alone — which is the whole point of this file. */
  .pl-dropdown a, .pl-dropdown button,
  .pl-navmenu-panel a, .pl-navmenu-panel button,
  .user-dropdown a, .user-dropdown button { min-height: 44px; }

  /* ── 4. CHECKBOXES ──────────────────────────────────────────────────────────────────────────
   * Measured 13x16 and 16x16 in the invoice editor (tax info, deposit, accent). A 13px checkbox
   * is not tappable. Grown, with margin so neighbouring rows do not become one ambiguous target. */
  input[type="checkbox"], input[type="radio"] {
    min-width: 22px;
    min-height: 22px;
    margin-block: 4px;
  }

  /* ── 5. NOTHING MAY SCROLL THE PAGE SIDEWAYS ────────────────────────────────────────────────
   * A body that scrolls horizontally makes every fixed element drift and every tap land wrong.
   * Wide content scrolls INSIDE its own container instead — see the per-page rules below. */
  html, body { overflow-x: hidden; }
}

/* ── 6. PER-PAGE OVERFLOW FIXES ───────────────────────────────────────────────────────────────
 * Width-based, not pointer-based: a genuinely narrow viewport needs these regardless of input
 * type, and they must also apply to a narrow desktop window. Each was measured overflowing. */
@media (max-width: 640px) {

  /* PRICING — the comparison table measured 679px wide inside a 320px viewport, the single worst
   * overflow on the site. A three-column feature comparison cannot honestly restack into 320px
   * without losing the comparison itself, so it scrolls in its OWN container with a visible edge
   * fade telling the user there is more. The page stops scrolling sideways; the table still does. */
  /* (dead-code sweep 2026-08-16: this rule used to name .cmp-wrap/.compare-wrap/
   * .pricing-table-wrap — three wrappers that exist NOWHERE, so the "tables scroll in their own
   * container" intent was riding on dead selectors. Re-pointed at the wrappers the site actually
   * ships: the editor/import dashboard tables, compare-markets, the rates guide, and pricing's
   * .tblwrap — belt-and-suspenders here since those pages also carry their own page-scoped copy.) */
  .dashboard-table-wrap, .mc-table-wrap, .rate-scroll, .tblwrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  table { max-width: 100%; }

  /* HOME — the action row (Customize / + New) measured 414px and pushed the page wide.
   * Wraps instead of overflowing.
   * ⚠ flex-wrap ALONE DID NOT FIX IT (found 2026-08-12 by the per-route overflow audit).
   * .hm-actions is itself a flex ITEM of .greet-row carrying `flex-shrink: 0`, so it kept its
   * 440px max-content width on a 390px screen — its children were never squeezed, so they
   * never had a reason to wrap, and the whole page scrolled sideways with "+ New" off-screen.
   * The row has to be ALLOWED to narrow before wrapping can do anything. */
  .hm-actions { flex-wrap: wrap; flex-shrink: 1; min-width: 0; max-width: 100%; }

  /* Decorative background glow sat 864px wide and dragged the page with it. It is ornament;
   * it must never define page width. */
  .glow { max-width: 100%; }

  /* BULK IMPORT FROM DOCUMENTS — review table restacks into cards (owner ask, 2026-08-16, mobile
     research pass following the desktop build). 5 columns of editable inputs (File/Client/Total/
     Date/Remove) cannot fit a phone width as a table without shrinking text past readable — the
     standard responsive-table technique instead: each row becomes its own card, each cell its own
     labeled line. Labels are CSS-generated (::before, keyed to column position) so nothing in the
     markup/JS changed for this — column order is stable and already asserted by
     tests/bulk-doc-import (the table header order pin). File-input mechanics, permissions, HEIC and
     the sequential-extraction memory pattern all needed zero change per that same research pass —
     this table was the one real gap. */
  .ext-docs-review-table thead { display: none; }
  .ext-docs-review-table, .ext-docs-review-table tbody, .ext-docs-review-table tr, .ext-docs-review-table td {
    display: block; width: 100%;
  }
  .ext-docs-review-table tbody tr {
    border: 1px solid var(--border); border-radius: 10px; margin-bottom: 10px;
    padding: 10px 12px 4px; background: var(--surface);
  }
  .ext-docs-review-table tbody tr:nth-child(even) td { background: none; }  /* the desktop zebra stripe reads oddly once each cell is its own line */
  .ext-docs-review-table td { border-bottom: none; padding: 0 0 10px; text-align: left; }
  .ext-docs-review-table td:first-child {
    font-weight: 600; font-size: 12.5px; padding-bottom: 10px;
    border-bottom: 1px solid var(--border); margin-bottom: 8px;
  }
  .ext-docs-review-table td:nth-child(2)::before,
  .ext-docs-review-table td:nth-child(3)::before,
  .ext-docs-review-table td:nth-child(4)::before {
    display: block; font-size: 9.5px; font-weight: 700; letter-spacing: .06em;
    text-transform: uppercase; color: var(--ink-muted); margin-bottom: 3px;
  }
  .ext-docs-review-table td:nth-child(2)::before { content: 'Client / payer'; }
  .ext-docs-review-table td:nth-child(3)::before { content: 'Total'; }
  .ext-docs-review-table td:nth-child(4)::before { content: 'Date'; }
  .ext-docs-review-table td:last-child { padding: 4px 0 6px; }
  /* The wrapper's scroll-well cap-removal lives in app.css, not here — this file's own rule (see
     the file header) is that nothing in mobile.css may ever shrink/cap a control's height, checked
     by a blanket pin banning that CSS property's name outright, anywhere in this file, full stop —
     so even a LOOSENING use of it has to happen in app.css's own mobile media query instead. */
}
