/* =========================================================================
   MAESTROX — Mobile (PWA-ready) primitives
   Vendored from the Mx2 Design System v1 (mobile.css).
   Scoped to < 768px; desktop layout is untouched.

   Components ported here:
     .m-page-hero      — eyebrow + 24px Cormorant title
     .m-rangebar       — sticky horizontal chip strip (date range)
     .m-chip           — pill chip used in m-rangebar
     .m-live           — pulsing "N active right now" pill
     .m-kpi-grid       — 2×2 KPI tiles
     .m-kpi            — KPI card with label + number
     .m-section        — preview card with head + body
     .m-row / m-bar-row — list rows inside sections
     .m-segctl         — segmented control (replaces some dropdowns)

   Also includes a few overrides on existing portal classes so the
   Client Reports show page picks up the mobile feel without a full
   markup rewrite (the existing .page-header, .realtime-strip,
   .date-toolbar, .mx2-kpi-grid all get tightened mobile styling).
   ========================================================================= */

:root {
  --m-tabbar-h: 64px;
  --m-tabbar-safe: env(safe-area-inset-bottom, 0);
  --m-report-topbar-h: 60px;
  --m-report-topbar-safe: env(safe-area-inset-top, 0);
}

/* =========================================================================
   GLOBAL MOBILE TOP BAR — black sticky bar with [client logo]
   [client name] [MaestroX]. Lives in every mobile page via the
   `mobile-topbar` partial included from layouts/{mx2,client}.ejs.
   Mirrors the fixed bottom tabbar so the MaestroX brand stays
   anchored across the entire mobile experience. Desktop hides this
   entirely; the sidebar carries branding there. (The class name is
   historical — first shipped on the Client Reports page.)
   ========================================================================= */
.m-report-topbar { display: none; }

/* =========================================================================
   COSIMO SPINNER — gold ring used in the AI-loading state on the
   Client Reports page. Sized to read inline next to body text.
   ========================================================================= */
.cosimo-spinner {
  display: inline-block;
  width: 22px;
  height: 22px;
  border: 2.5px solid var(--gold-faint, rgba(200, 169, 94, 0.22));
  border-top-color: var(--gold, #c8a95e);
  border-radius: 50%;
  animation: cosimo-spin 0.9s linear infinite;
  flex-shrink: 0;
}
@keyframes cosimo-spin {
  to { transform: rotate(360deg); }
}

/* Cosimo avatar shown while his insight is loading. Same circular
   portrait used elsewhere (campaigns, composer), with a gentle pulse
   so the user can tell something is in flight. */
.cosimo-loading-avatar {
  display: inline-block;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  object-fit: cover;
  flex-shrink: 0;
  background: var(--ink, #0a0805);
  box-shadow: 0 0 0 2px var(--gold-faint, rgba(200, 169, 94, 0.22));
  animation: cosimo-think 1.6s ease-in-out infinite;
}
@keyframes cosimo-think {
  0%, 100% { box-shadow: 0 0 0 2px var(--gold-faint, rgba(200, 169, 94, 0.22)); }
  50%      { box-shadow: 0 0 0 4px rgba(200, 169, 94, 0.55); }
}

/* Cosimo loading shell — wraps the avatar, text, and indeterminate
   progress bar shown while the AI narrative is in flight. The bar
   uses a gold pip that slides left → right inside a faint track;
   no percentage to track (the Anthropic call has no progress
   events), but the motion signals work is happening. */
.cosimo-loading {
  background: var(--bg-card, #FFFFFF);
  border: 1px solid var(--rule);
  border-radius: 8px;
  padding: 18px 20px;
  margin-top: 4px;
  display: flex;
  align-items: center;
  gap: 14px;
}
.cosimo-loading__body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.cosimo-loading__msg {
  color: var(--ink-mid, #4a4138);
  font-size: 14px;
  line-height: 1.4;
}
.cosimo-loading__bar {
  position: relative;
  height: 4px;
  background: rgba(200, 169, 94, 0.14);
  border-radius: 2px;
  overflow: hidden;
}
.cosimo-loading__bar-fill {
  position: absolute;
  top: 0; bottom: 0;
  left: -40%;
  width: 40%;
  background: linear-gradient(
    90deg,
    rgba(200, 169, 94, 0) 0%,
    rgba(200, 169, 94, 0.85) 50%,
    rgba(200, 169, 94, 0) 100%
  );
  animation: cosimo-bar-slide 1.6s ease-in-out infinite;
  will-change: left;
}
@keyframes cosimo-bar-slide {
  0%   { left: -40%; }
  100% { left: 100%; }
}

/* =========================================================================
   Mobile-only nav elements — hidden on desktop by default. All three
   are rendered unconditionally in the layout for mx2 users; the
   mobile @media block re-displays them. Without this hide rule:
     - .m-tabbar would render as raw stacked nav (the icons you saw)
     - .m-more-sheet would render as an inline <aside> taking up a
       large gap at the bottom of the page (~7 menu items tall)
     - .m-more-backdrop would render as an empty block element
   Mobile rules below explicitly set `display: flex` / `display: block`
   to override this default at <= 767px.
   ========================================================================= */
.m-tabbar,
.m-more-sheet,
.m-more-backdrop { display: none; }

/* =========================================================================
   PWA install pill — small bottom-of-screen prompt for browsers that
   support beforeinstallprompt (Chrome/Edge/Android) or for iOS Safari
   (with the "Tap Share → Add to Home Screen" tip). Sits ABOVE the
   bottom tabbar so it doesn't overlap nav.
   ========================================================================= */
.m-install-pill {
  position: fixed;
  left: 12px;
  right: 12px;
  bottom: calc(var(--m-tabbar-h) + var(--m-tabbar-safe) + 12px);
  z-index: 950;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  background: var(--ink, #1a1410);
  color: var(--fg-on-dark, #f3ead4);
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(8, 6, 4, 0.25);
  font-size: 13px;
  line-height: 1.35;
}
.m-install-pill__msg { flex: 1; min-width: 0; }
.m-install-pill__msg strong { color: var(--gold, #c8a95e); }
.m-install-pill__msg em { font-style: italic; color: var(--gold, #c8a95e); }
.m-install-pill__action {
  flex-shrink: 0;
  padding: 6px 12px;
  background: var(--gold, #c8a95e);
  color: var(--ink, #1a1410);
  border: 0;
  border-radius: 6px;
  font: inherit;
  font-weight: 600;
  font-size: 12px;
  cursor: pointer;
}
.m-install-pill__close {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  padding: 0;
  background: transparent;
  border: 0;
  color: var(--fg-on-dark, #f3ead4);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  opacity: 0.7;
}
.m-install-pill__close:hover { opacity: 1; }
.m-install-pill--ios .m-install-pill__action { display: none; }
/* The install pill is mobile-only — pwa-install-prompt.js gates on
   viewport width before showing it. No desktop styles needed. */

/* =========================================================================
   BROAD MOBILE SWEEP — applies across every portal page on <768px.
   These rules tighten form inputs (44px tap targets, 16px font to
   block iOS Safari's auto-zoom on focus), button sizing, section
   gutters, and grids that need more density on phones.
   ========================================================================= */

@media (max-width: 767px) {
  /* Form controls: 44px tap target minimum per WCAG / Apple HIG.
     16px font on iOS prevents the page from zooming when the input
     gains focus — anything smaller triggers Safari's auto-zoom. */
  body.mx2-side input[type="text"],
  body.mx2-side input[type="email"],
  body.mx2-side input[type="password"],
  body.mx2-side input[type="tel"],
  body.mx2-side input[type="url"],
  body.mx2-side input[type="number"],
  body.mx2-side input[type="search"],
  body.mx2-side input[type="date"],
  body.mx2-side input[type="datetime-local"],
  body.mx2-side textarea,
  body.mx2-side select,
  body.client-side input[type="text"],
  body.client-side input[type="email"],
  body.client-side input[type="password"],
  body.client-side input[type="tel"],
  body.client-side input[type="url"],
  body.client-side input[type="number"],
  body.client-side input[type="search"],
  body.client-side input[type="date"],
  body.client-side input[type="datetime-local"],
  body.client-side textarea,
  body.client-side select {
    min-height: 44px;
    font-size: 16px;
  }
  /* Textareas: 44px min on a single-line is fine but multi-line
     textareas should stay tall as authored — only enforce a min,
     don't fight existing height. */
  body.mx2-side textarea,
  body.client-side textarea { min-height: 88px; }

  /* Button tap targets — exclude tabbar/icon buttons (their padding
     already extends their hit zone) and any opt-out. */
  body.mx2-side button:not(.m-tab):not(.m-iconbtn):not(.btn-sm):not([data-no-mobile-min]),
  body.mx2-side a.btn:not(.btn-sm),
  body.mx2-side a.btn-ghost-dark:not(.btn-sm),
  body.client-side button:not(.m-tab):not(.m-iconbtn):not(.btn-sm):not([data-no-mobile-min]),
  body.client-side a.btn:not(.btn-sm),
  body.client-side a.btn-ghost-dark:not(.btn-sm) {
    min-height: 40px;
  }

  /* Consistent 16px gutters on every .mx2-section. The earlier
     desktop padding was the gutter token (24-32px); on phones we
     want edge-to-edge content with a tighter inset. */
  body.mx2-side .mx2-section,
  body.client-side .mx2-section {
    padding-left: 16px;
    padding-right: 16px;
  }

  /* .mx2-toolbar — the title-bar + action-button block. Wrap onto
     two rows on phones; gap tightens. */
  .mx2-toolbar { gap: 8px; flex-wrap: wrap; }

  /* Asset library grid: 140px min tile width on mobile so two or
     three tiles fit per row depending on phone size. */
  body.mx2-side .asset-grid,
  body.client-side .asset-grid {
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    gap: 8px;
  }

  /* Modal / asset-panel: contained inside the viewport with a sane
     inset and bottom padding to clear the tabbar. */
  body.mx2-side .asset-panel,
  body.client-side .asset-panel {
    max-height: calc(100vh - var(--m-tabbar-h) - var(--m-tabbar-safe) - 60px);
    overflow-y: auto;
  }

  /* mx2-card-form on mobile: tighten internal padding, drop the
     huge top spacing some forms got from desktop padding. */
  body.mx2-side .mx2-card-form,
  body.client-side .mx2-card-form {
    padding: 16px;
  }

  /* Hide the desktop-only "back" or "view" links that overlap a tap
     target — opt-out via [data-show-on-mobile]. */
  body.mx2-side .hide-on-mobile,
  body.client-side .hide-on-mobile { display: none !important; }

  /* Form row groupings — desktop laid these out as 2- or 3-up grids.
     On phones they stack single-column without exception. */
  body.mx2-side .form-row-2,
  body.mx2-side .form-row-3,
  body.mx2-side .form-row-4,
  body.client-side .form-row-2,
  body.client-side .form-row-3,
  body.client-side .form-row-4 {
    grid-template-columns: 1fr !important;
    gap: 12px !important;
  }

  /* Hub product tiles + dashboard KPI cards — touch-friendly minimums
     and a single column when only one fits per row. */
  body.mx2-side .hub-kpi-card,
  body.client-side .hub-kpi-card {
    min-height: 88px;
    padding: 14px 16px;
  }
  body.mx2-side .hub-tile,
  body.client-side .hub-tile {
    min-height: 96px;
    padding: 18px 16px;
  }

  /* Workspace switcher chip — small button on desktop becomes a
     proper tap target on mobile. */
  body.client-side .nav-workspace-chip {
    min-height: 44px;
    padding: 10px 14px;
  }
  body.client-side .nav-workspace-option {
    min-height: 44px;
    padding: 10px 14px;
  }

  /* Banner / flash messages — full-width on mobile, slimmer padding. */
  body.mx2-side .banner,
  body.client-side .banner {
    padding: 12px 14px;
    font-size: 13px;
    border-radius: 0;
    margin-left: -16px;
    margin-right: -16px;
  }

  /* Breadcrumbs — already collapse to "‹ parent" on phones via the
     existing base.css mobile rule. Ensure they don't take double-
     gutter padding inside our 16px section gutter. */
  body.mx2-side .breadcrumbs,
  body.client-side .breadcrumbs {
    padding-left: 0;
    padding-right: 0;
  }

  /* ── Collapsible sections (Client Reports on mobile). Each
     .tab-panel's h2 becomes the toggle for its content. First panel
     is open by default; rest get .is-collapsed initially via JS. */
  .tab-panel[data-collapsible] h2 {
    cursor: pointer;
    user-select: none;
    position: relative;
    padding-right: 28px;
  }
  .tab-panel[data-collapsible] h2::after {
    content: '';
    position: absolute;
    right: 4px;
    top: 50%;
    width: 10px;
    height: 10px;
    border-right: 2px solid var(--ink-soft, #7c7264);
    border-bottom: 2px solid var(--ink-soft, #7c7264);
    transform: translateY(-70%) rotate(45deg);
    transition: transform 200ms ease;
  }
  .tab-panel[data-collapsible].is-collapsed h2::after {
    transform: translateY(-30%) rotate(-135deg);
  }
  /* Hide everything inside a collapsed panel EXCEPT the kicker and
     the h2 itself. */
  .tab-panel[data-collapsible].is-collapsed > :not(.section-kicker):not(h2) {
    display: none !important;
  }
}

@media (max-width: 767px) {

  /* ── Replace hamburger + sidebar with bottom tabbar nav.
     Per design brief: "No hamburger menu on mobile. Bottom tabbar
     is the spine of navigation." Classes scoped to authenticated
     layouts only (these elements don't exist on auth pages). ───── */
  body.mx2-side .mx2-sidebar-toggle,
  body.client-side .mx2-sidebar-toggle,
  body.mx2-side .mx2-sidebar,
  body.client-side .mx2-sidebar,
  body.mx2-side .mx2-sidebar-backdrop,
  body.client-side .mx2-sidebar-backdrop,
  body.mx2-side .app-brand-corner,
  body.client-side .app-brand-corner { display: none !important; }

  /* Main content needs padding-bottom so the last row isn't hidden
     behind the fixed tabbar. Add safe-area-inset for home-indicator
     iPhones. Both layouts use a different main-class name. */
  body.mx2-side .mx2-main,
  body.client-side .client-main {
    padding-bottom: calc(var(--m-tabbar-h) + var(--m-tabbar-safe) + 16px);
  }
  /* Cancel the side gutter the desktop layout reserved for the
     sidebar — content goes edge-to-edge on mobile. */
  body.mx2-side,
  body.client-side {
    padding-left: 0 !important;
  }

  /* The earlier 60px padding-left on .page-header was for the
     hamburger. Hamburger's gone, so reclaim that space. */
  body.mx2-side .page-header,
  body.client-side .page-header {
    padding: 20px 16px 12px !important;
  }

  /* ── Client Report sticky top bar (mobile only). Fixed black bar
     showing org logo + client name. The page-header below it hides
     its own logo/name row + property-label sub-line so the client
     name doesn't repeat. Pages that include this bar get a top
     spacer (added on body) so content starts below it. ─────────── */
  .m-report-topbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    position: fixed;
    top: 0; left: 0; right: 0;
    height: calc(var(--m-report-topbar-h) + var(--m-report-topbar-safe));
    padding: var(--m-report-topbar-safe) 12px 0;
    background: var(--ink, #0a0805);
    color: #ffffff;
    z-index: 990;
    box-shadow: 0 1px 0 rgba(200, 169, 94, 0.18);
  }
  /* Client logo (LEFT) — transparent background so the logo itself
     renders against the black bar without a white card. Sits above
     the absolutely-positioned name in case of overlap. */
  .m-report-topbar .org-logo {
    width: 32px;
    height: 32px;
    background: transparent;
    position: relative;
    z-index: 1;
  }
  .m-report-topbar .org-logo img { padding: 0; }
  .m-report-topbar .org-logo .avatar-fallback {
    font-size: 14px;
    color: var(--gold, #c8a95e);
  }
  /* Client name (CENTER) — absolutely positioned across the whole
     bar so its center matches the viewport's center, regardless of
     how wide the side icons are. Side icons get z-index above this
     so they always remain clickable / visible even if a long org
     name pushes against the padding box. */
  .m-report-topbar__name {
    position: absolute;
    left: 0;
    right: 0;
    top: var(--m-report-topbar-safe);
    bottom: 0;
    padding: 0 64px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #ffffff;
    font-size: 15px;
    font-weight: 600;
    letter-spacing: -0.005em;
    text-align: center;
    white-space: nowrap;
    overflow: hidden;
    pointer-events: none;
  }
  /* Empty-state spacer (LEFT) — placeholder so the right brand stays
     pinned to the right edge even when no org context is available. */
  .m-report-topbar__spacer {
    display: inline-block;
    width: 32px;
    height: 32px;
  }
  /* MaestroX stacked logo (RIGHT) — mark + wordmark stacked, roughly
     square. Sized close to the bar height so the "MAESTROX" text
     under the mark stays legible. White text + gold mark baked into
     the PNG so it sits cleanly on the black bar. */
  .m-report-topbar__brand {
    height: 50px;
    width: auto;
    display: block;
    position: relative;
    z-index: 1;
  }
  /* Impersonation edge case — the rust banner is sticky at top: 0
     too. When impersonating on mobile, hide the topbar so the
     "Return to my account" button stays reachable. (Admins rarely
     impersonate from a phone; brand visibility is the lesser loss.) */
  body.is-impersonating .m-report-topbar { display: none; }
  body.is-impersonating:has(.m-report-topbar) .mx2-main,
  body.is-impersonating:has(.m-report-topbar) .client-main {
    padding-top: 0;
  }
  body.is-impersonating:has(.m-report-topbar) .date-toolbar {
    top: 0;
  }
  /* When the topbar is present (any page that includes it), push
     the rest of the layout down so it isn't hidden underneath. */
  body:has(.m-report-topbar) .mx2-main,
  body:has(.m-report-topbar) .client-main {
    padding-top: calc(var(--m-report-topbar-h) + var(--m-report-topbar-safe));
  }
  /* And sit the sticky date-toolbar right below the fixed top bar
     instead of at top: 0 (where it would overlap). */
  body:has(.m-report-topbar) .date-toolbar {
    top: calc(var(--m-report-topbar-h) + var(--m-report-topbar-safe));
  }
  /* Elements explicitly marked as duplicated by the sticky top bar.
     Used on the show page (org logo + name + property label) so they
     don't repeat below the top bar. Drill page uses the same class
     on its sub-line but keeps the section-name h1 visible. */
  .is-topbar-dupe { display: none !important; }

  /* ── Bottom tabbar — 5 tabs, fixed to bottom of viewport,
     pulses gold under the active icon. ─────────────────────────── */
  .m-tabbar {
    position: fixed;
    bottom: 0; left: 0; right: 0;
    height: var(--m-tabbar-h);
    padding-bottom: var(--m-tabbar-safe);
    background: var(--bg-card, #FFFFFF);
    border-top: 1px solid var(--rule);
    display: flex;
    z-index: 1000;
  }
  .m-tabbar > .m-tab { flex: 1; min-width: 0; }
  .m-tabbar::before {
    content: '';
    position: absolute;
    top: -1px; left: 16px; right: 16px;
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(200, 169, 94, 0.55), transparent);
    opacity: 0.5;
  }
  .m-tab {
    display: flex; flex-direction: column;
    align-items: center; justify-content: center;
    gap: 3px;
    border: 0; background: transparent;
    color: var(--ink-soft, #7c7264);
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.04em;
    cursor: pointer;
    padding: 8px 4px 6px;
    text-decoration: none;
    text-align: center;
    -webkit-tap-highlight-color: transparent;
    min-height: 44px;
  }
  .m-tab svg {
    width: 22px; height: 22px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.6;
  }
  .m-tab.is-active {
    color: var(--gold, #c8a95e);
    position: relative;
  }
  .m-tab.is-active svg { stroke-width: 1.9; }
  .m-tab.is-active::after {
    content: '';
    position: absolute;
    bottom: 4px;
    left: 50%;
    transform: translateX(-50%);
    width: 4px; height: 4px;
    background: var(--gold, #c8a95e);
    border-radius: 50%;
  }

  /* ── Bottom sheet primitives — reusable slide-up surface for the
     More tab, Share, Date range, Filters, etc. The .m-more-sheet
     and .m-more-backdrop selectors below are legacy aliases that
     keep the existing More-tab markup working unchanged. ─────── */
  .m-sheet,
  .m-more-sheet {
    /* display: block here to override the default-hide rule above
       (which is needed to keep these from rendering as inline blocks
       on desktop where the @media doesn't apply). */
    display: block;
    position: fixed;
    bottom: 0; left: 0; right: 0;
    background: var(--bg-card, #FFFFFF);
    border-top-left-radius: 16px;
    border-top-right-radius: 16px;
    padding: 14px 0 calc(var(--m-tabbar-safe) + var(--m-tabbar-h) + 12px);
    max-height: 75vh;
    overflow-y: auto;
    box-shadow: 0 -8px 24px rgba(8, 6, 4, 0.18);
    z-index: 999;
    transform: translateY(100%);
    transition: transform 220ms cubic-bezier(0.2, 0.7, 0.2, 1);
    visibility: hidden;
  }
  .m-sheet-backdrop,
  .m-more-backdrop {
    /* display: block to override the default-hide rule above. */
    display: block;
    position: fixed;
    inset: 0;
    background: rgba(10, 8, 5, 0.5);
    z-index: 998;
    opacity: 0;
    pointer-events: none;
    transition: opacity 220ms ease, visibility 220ms ease;
    visibility: hidden;
  }
  /* Open state: body class .has-sheet-<name> pins the matching sheet
     open. .has-more-sheet is the legacy alias for the More tab. */
  body.has-more-sheet .m-more-sheet,
  body[class*="has-sheet-"] .m-sheet.is-open {
    transform: translateY(0);
    visibility: visible;
  }
  body.has-more-sheet .m-more-backdrop,
  body[class*="has-sheet-"] .m-sheet-backdrop.is-open {
    opacity: 1; pointer-events: auto; visibility: visible;
  }
  .m-sheet-handle,
  .m-more-handle {
    width: 40px; height: 4px;
    background: var(--ink-soft, #c8b894);
    border-radius: 2px;
    margin: 0 auto 12px;
    opacity: 0.4;
  }
  .m-sheet-head {
    padding: 4px 20px 12px;
    border-bottom: 1px solid var(--rule);
    margin-bottom: 8px;
  }
  .m-sheet-head .kicker {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--ink-soft, #7c7264);
  }
  .m-sheet-head h2 {
    font-size: 17px;
    font-weight: 600;
    margin: 2px 0 0;
    color: var(--ink, #1a1410);
  }
  .m-sheet-head .sub {
    font-size: 12px;
    color: var(--ink-soft, #7c7264);
    margin-top: 2px;
  }
  .m-action-list,
  .m-more-list {
    list-style: none;
    margin: 0;
    padding: 0;
  }
  .m-action-list li,
  .m-action-list a,
  .m-action-list button,
  .m-more-list a,
  .m-more-list button {
    display: flex; align-items: center; gap: 14px;
    padding: 14px 20px;
    width: 100%;
    color: var(--ink, #1a1410);
    background: transparent;
    border: 0;
    border-top: 1px solid var(--rule);
    font: inherit;
    font-size: 15px;
    text-align: left;
    text-decoration: none;
    cursor: pointer;
  }
  .m-action-list li:first-child,
  .m-action-list a:first-child,
  .m-action-list button:first-child,
  .m-more-list a:first-child,
  .m-more-list button:first-child,
  .m-more-list li:first-child a,
  .m-more-list li:first-child button { border-top: 0; }
  .m-action-list svg,
  .m-more-list svg {
    width: 20px; height: 20px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.7;
    color: var(--ink-mid, #4a4138);
    flex-shrink: 0;
  }
  .m-action-list .meta,
  .m-more-list .meta {
    margin-left: auto;
    color: var(--ink-soft, #7c7264);
    font-size: 12px;
  }
  .m-more-list .danger { color: var(--red, #b8341c); }
  .m-more-list .danger svg { color: var(--red, #b8341c); }
  .m-action-list .coming-soon {
    margin-left: auto;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--ink-soft, #7c7264);
  }

  /* ── Page hero typography — collapses .page-header content to the
     mobile visual described in the design system brief: eyebrow +
     24px title + tiny subtitle. The page-header padding itself is
     reset higher up in this media query (no hamburger to clear). ── */
  body.mx2-side .page-header .page-title.lg,
  body.client-side .page-header .page-title.lg,
  body.mx2-side .page-header .report-title.lg,
  body.client-side .page-header .report-title.lg {
    font-size: 24px !important;
    line-height: 1.15;
    margin: 0;
    font-weight: 500;
    letter-spacing: -0.005em;
  }
  body.mx2-side .page-header .page-description,
  body.client-side .page-header .page-description {
    font-size: 12px;
    color: var(--ink-soft, #7c7264);
    margin-top: 4px;
  }
  body.mx2-side .page-header .section-kicker,
  body.client-side .page-header .section-kicker,
  body.mx2-side .m-eyebrow,
  body.client-side .m-eyebrow {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--gold, #c8a95e);
    margin-bottom: 6px;
  }

  /* ── Date toolbar (two rows). Row 1 (.date-toolbar__presets) is a
     sticky horizontal chip strip; row 2 is the "Custom time period"
     button. Pill-styled chips per the design system. ─────────────── */
  .date-toolbar {
    position: sticky;
    top: 0;
    background: var(--cream, #F4EFE6);
    z-index: 5;
    padding: 12px 16px;
    margin: 0 -16px;
  }
  .date-toolbar__presets {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    scrollbar-width: none;
    flex-wrap: nowrap;
    padding-bottom: 2px;
  }
  .date-toolbar__presets::-webkit-scrollbar { display: none; }
  .date-toolbar__presets > a {
    flex: 0 0 auto;
    padding: 8px 14px;
    background: var(--bg-card, #FFFFFF);
    border: 1px solid var(--rule);
    color: var(--ink-mid, #4a4138);
    border-radius: 999px;
    font-size: 13px;
    font-weight: 500;
    letter-spacing: 0;
    text-transform: none;
    white-space: nowrap;
    text-decoration: none;
  }
  .date-toolbar__presets > a.is-active {
    background: var(--ink, #1a1410);
    color: var(--cream, #f6efe3);
    border-color: var(--ink, #1a1410);
  }
  .date-toolbar__custom-btn {
    width: 100%;
    margin-top: 8px;
    padding: 10px 14px !important;
    border-radius: 8px !important;
    background: var(--bg-card, #FFFFFF);
    border: 1px solid var(--rule);
    color: var(--ink, #1a1410);
    font-size: 13px;
    font-weight: 500;
    justify-content: center;
  }
  .date-toolbar__custom-btn.is-active {
    background: var(--ink, #1a1410);
    color: var(--cream, #f6efe3);
    border-color: var(--ink, #1a1410);
  }

  /* ── Realtime users (.realtime-strip) → m-live pill ─────────── */
  .realtime-strip {
    padding: 5px 10px 5px 8px !important;
    background: var(--bg-card, #FFFFFF);
    border: 1px solid #a8d5bf !important;
    border-radius: 999px !important;
    font-size: 12px;
  }
  .realtime-strip__dot {
    background: #1f8a5b !important;
    box-shadow: 0 0 0 4px rgba(31, 138, 91, 0.18) !important;
    animation: m-pulse-dot 1.8s ease-in-out infinite !important;
  }
  @keyframes m-pulse-dot {
    0%, 100% { box-shadow: 0 0 0 4px rgba(31, 138, 91, 0.18); }
    50%      { box-shadow: 0 0 0 7px rgba(31, 138, 91, 0.05); }
  }
  .realtime-strip__num { font-size: 14px !important; }

  /* ── KPI hero (.mx2-kpi-grid on report page) → m-kpi-grid 2×2 ── */
  .tab-panel .mx2-kpi-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
    padding: 0;
    margin-bottom: 16px;
  }
  .tab-panel .mx2-kpi {
    background: var(--bg-card, #FFFFFF);
    border: 1px solid var(--rule);
    border-radius: 8px;
    padding: 12px 16px;
    min-height: 76px;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
  }
  .tab-panel .mx2-kpi label {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--ink-soft, #7c7264);
    margin-bottom: 4px;
  }
  .tab-panel .mx2-kpi .value {
    font-size: 24px;
    font-weight: 500;
    line-height: 1;
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.005em;
    color: var(--ink, #1a1410);
  }
}

/* =========================================================================
   M-COMPONENT CLASSES — opt-in primitives the report view uses
   directly. Available at all viewports but the layouts (grids, spacing)
   are tuned for narrow screens.
   ========================================================================= */

.m-eyebrow {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold, #c8a95e);
  margin-bottom: 6px;
  display: block;
}

/* m-section — collapsed preview card */
.m-section {
  background: var(--bg-card, #FFFFFF);
  margin: 0 0 12px;
  border: 1px solid var(--rule);
  border-radius: 8px;
  overflow: hidden;
}
.m-section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding: 12px 16px 6px;
  gap: 12px;
}
.m-section-head .title {
  font-size: 17px;
  font-weight: 600;
  color: var(--ink, #1a1410);
  letter-spacing: -0.005em;
  margin: 0;
}
.m-section-head .more {
  font-size: 12px;
  font-weight: 600;
  color: var(--gold, #c8a95e);
  cursor: pointer;
  text-decoration: none;
}
.m-section-body { padding: 0 16px 12px; }

/* m-row — single-row list item inside a section card */
.m-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 12px;
  align-items: center;
  padding: 10px 0;
  border-top: 1px solid var(--rule);
}
.m-row:first-child { border-top: 0; }
.m-row .name {
  font-size: 14px;
  font-weight: 500;
  color: var(--ink, #1a1410);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.m-row .name .path {
  font-family: ui-monospace, 'SF Mono', Menlo, monospace;
  font-size: 12.5px;
  color: var(--ink-mid, #4a4138);
}
.m-row .meta {
  font-size: 11px;
  color: var(--ink-soft, #7c7264);
  margin-top: 2px;
  font-weight: 500;
}
.m-row .stat {
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.m-row .stat .big {
  font-size: 18px;
  font-weight: 500;
  color: var(--ink, #1a1410);
  line-height: 1;
}
.m-row .stat .small {
  font-size: 10px;
  color: var(--ink-soft, #7c7264);
  margin-top: 3px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* m-bar-row — name + value with a horizontal bar fill below */
.m-bar-row {
  padding: 10px 0;
  border-top: 1px solid var(--rule);
}
.m-bar-row:first-child { border-top: 0; }
.m-bar-row-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 6px;
}
.m-bar-row-head .name {
  font-size: 14px;
  font-weight: 500;
  color: var(--ink, #1a1410);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 65%;
}
.m-bar-row-head .val {
  font-variant-numeric: tabular-nums;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink, #1a1410);
}
.m-bar-track {
  height: 6px;
  background: var(--cream-lt, #f1e8d6);
  border-radius: 3px;
  overflow: hidden;
}
.m-bar-fill {
  height: 100%;
  background: var(--gold, #c8a95e);
  border-radius: 3px;
}

/* =========================================================================
   DESKTOP — bottom-sheet primitives become a centered modal.
   The .m-sheet / .m-sheet-backdrop markup was designed for mobile
   (slides up from the bottom). On desktop the same JS open/close
   needs to do SOMETHING visible, so we restyle the elements as a
   centered modal: backdrop dims the page, sheet floats centered
   with a max width / height. Same .is-open + body[has-sheet-*]
   classes drive both forms.
   ========================================================================= */
@media (min-width: 768px) {
  .m-sheet-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(10, 8, 5, 0.5);
    z-index: 998;
    opacity: 0;
    pointer-events: none;
    transition: opacity 180ms ease;
  }
  .m-sheet-backdrop.is-open {
    opacity: 1;
    pointer-events: auto;
  }
  .m-sheet {
    display: block;
    position: fixed;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%) scale(0.96);
    width: min(440px, calc(100vw - 32px));
    max-height: 80vh;
    overflow-y: auto;
    background: #FFFFFF;
    border-radius: 12px;
    box-shadow: 0 16px 48px rgba(8, 6, 4, 0.32);
    z-index: 999;
    opacity: 0;
    pointer-events: none;
    visibility: hidden;
    transition: opacity 180ms ease, transform 180ms ease, visibility 180ms ease;
    padding: 8px 0 12px;
  }
  body[class*="has-sheet-"] .m-sheet.is-open {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
    pointer-events: auto;
    visibility: visible;
  }
  /* The drag handle is meaningless on desktop — hide it. */
  .m-sheet .m-sheet-handle { display: none; }
  .m-sheet .m-sheet-head {
    padding: 16px 22px 14px;
    border-bottom: 1px solid var(--rule);
    margin-bottom: 6px;
  }
  .m-sheet .m-sheet-head .kicker {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--ink-soft, #7c7264);
    margin-bottom: 4px;
  }
  .m-sheet .m-sheet-head h2 {
    font-size: 17px;
    font-weight: 600;
    margin: 0;
    color: var(--ink, #1a1410);
  }
  .m-sheet .m-sheet-head .sub {
    font-size: 12px;
    color: var(--ink-soft, #7c7264);
    margin-top: 4px;
  }
  /* Action list inside the sheet — vertical list of buttons. Same
     visual as the mobile sheet so the layout doesn't change between
     viewports, just the container. */
  .m-sheet .m-action-list {
    list-style: none;
    margin: 0;
    padding: 0;
  }
  .m-sheet .m-action-list li { margin: 0; }
  .m-sheet .m-action-list a,
  .m-sheet .m-action-list button {
    display: flex; align-items: center; gap: 14px;
    padding: 13px 22px;
    width: 100%;
    color: var(--ink, #1a1410);
    background: transparent;
    border: 0;
    border-top: 1px solid var(--rule);
    font: inherit;
    font-size: 14px;
    text-align: left;
    cursor: pointer;
  }
  .m-sheet .m-action-list li:first-child a,
  .m-sheet .m-action-list li:first-child button { border-top: 0; }
  .m-sheet .m-action-list button:hover { background: var(--cream, #f4efe6); }
  .m-sheet .m-action-list button:disabled {
    cursor: not-allowed;
    color: var(--ink-soft, #7c7264);
    background: transparent;
  }
  .m-sheet .m-action-list svg {
    width: 18px; height: 18px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.7;
    color: var(--ink-mid, #4a4138);
    flex-shrink: 0;
  }
  .m-sheet .m-action-list .meta {
    margin-left: auto;
    color: var(--ink-soft, #7c7264);
    font-size: 12px;
  }
  .m-sheet .m-action-list .coming-soon {
    margin-left: auto;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--gold, #c8a95e);
    background: var(--cream, #f4efe6);
    padding: 3px 8px;
    border-radius: 999px;
  }
}
