/* ============================================================================
   css/v2-mobile.css — dashboard mobile pass (P0 + polish round 2)
   ----------------------------------------------------------------------------
   Every rule in this file lives inside a max-width media query, so the file is
   invisible at the golden-gate 1440×900 viewport by construction — no baseline
   recapture needed. Loaded LAST (after audit.css) so it wins the cascade over
   layout/components/v2-theme/v2-shell at equal specificity.

   Round 2 (Daniel's live-device review): the triage layout was collision-free
   but read as accidental — three ragged header rows, a floating CTA, two-line
   compare bar, untouched Results head. This pass makes the chrome look
   designed: two balanced header rows, one-line compare bar, stacked page head
   with full-width action buttons, one-line scrolling section pills.
   ============================================================================ */

/* ── 1. Header → exactly two rows.
   Row 1: hamburger · logo ········ trust pill · Demo pill · logout
   Row 2: tenant name (truncates) ········ get-started CTA
   display:contents lifts the .header-left/right children into the header's own
   wrapping flex context — zero DOM changes. The tenant block's flex-basis
   (100% minus the CTA's footprint) forces the wrap onto row 2; the CTA then
   shares that row and the name ellipsizes into the leftover space.
   Breakpoint is 900px: with tenant name + demo CTA visible, one 64px row is
   already too tight in the 769–900px band. ── */
@media (max-width: 900px) {
  :root { --header-height: 98px; }

  .header {
    flex-wrap: wrap;
    align-content: center;
    justify-content: flex-start;
    padding: 0 14px;
    column-gap: 12px;
    row-gap: 2px;
  }
  .header-left,
  .header-right { display: contents; }

  /* Row 1 — consistent 40px control heights, everything optically centered */
  .hamburger {
    order: 1;
    width: 40px;
    height: 40px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    margin-left: -10px;
  }
  .header-logo { order: 2; height: 24px; }
  .header-divider { display: none; }
  /* The right cluster must hug the right edge whichever badges are visible.
     The QA pill is HIDDEN on the demo tenant, so it can't be the only carrier
     of the auto margin (that left the Demo pill + logout packed left with a
     dead right half — Daniel's device review r3). Every cluster member gets
     margin-left:auto; hidden ones are inert. In practice exactly one carrier
     renders per mode (QA pill on real tenants, Demo pill on demo), so the
     cluster stays flush right; if two ever show, the space splits evenly. */
  .qa-pill { order: 3; margin-left: auto; }
  .header-mode-badge { order: 4; margin-left: auto; }
  .header-badge.demo {
    order: 5;
    flex: none;
    margin-left: auto;
    padding: 3px 9px;
    font-size: 10.5px;
    white-space: nowrap;
  }
  .header-updated { display: none; }
  .header-logout {
    order: 6;
    flex: none;
    width: 36px;
    height: 36px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    margin-right: -6px;
  }
  .header-logout span { display: none; }

  /* Row 2 — tenant identity + CTA share the line; the name gives way first */
  .header-client-switcher,
  .header-client {
    order: 7;
    flex: 1 1 calc(100% - 220px); /* > row-1 leftover ⇒ forces the wrap */
    min-width: 0;
  }
  .header-client-name,
  .header-client-domain {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .header-client-name { font-size: 14.5px; line-height: 1.25; }
  .header-getstarted-cta {
    order: 8;
    flex: 0 0 auto;
    margin-left: auto;
    padding: 6px 12px;
    font-size: 11px;
  }
}
/* Phone: domain line off (the name is the identity; the domain is noise at
   this size) — buys the name ~2× the room next to the CTA. */
@media (max-width: 600px) {
  .header-client-domain { display: none; }
  .header-getstarted-cta svg { display: none; } /* arrow: ~20px back to the name */
}

/* ── 2. Product-chip row: scroll affordance + touch feel. The fade sits on the
   row (not the scroller) so it stays pinned while chips scroll under it. ── */
@media (max-width: 768px) {
  body.v2-shell .v2-topbar-products { position: relative; }
  body.v2-shell .v2-topbar-products::after {
    content: "";
    position: absolute;
    top: 0;
    right: 0;
    bottom: 1px; /* keep the row's own border visible */
    width: 32px;
    background: linear-gradient(to left, #FFFFFF 20%, rgba(255, 255, 255, 0));
    pointer-events: none;
  }
  body.v2-shell .v2-topbar-products .v2-topbar-inner {
    padding-right: 40px; /* last chip clears the fade */
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
    scroll-snap-type: x proximity;
  }
  body.v2-shell .v2-topbar-products .v2-topbar-inner::-webkit-scrollbar { display: none; }
  body.v2-shell .v2-product {
    min-height: 44px; /* touch target */
    scroll-snap-align: start;
  }

  /* ── 3. Compare row → ONE quiet line: window text + help. The legend is
     redundant (delta pills carry their own arrows in-context) and the
     highlight-changes pulse is a desktop reviewing tool — both off here. ── */
  body.v2-shell .v2-compare-legend,
  body.v2-shell .v2-compare-toggle,
  body.v2-shell .v2-compare-eyebrow { display: none; }
  body.v2-shell .v2-topbar-compare .v2-topbar-inner {
    flex-wrap: nowrap;
    padding-top: 8px;
    padding-bottom: 8px;
    gap: 10px;
  }
  body.v2-shell .v2-compare-window {
    min-width: 0;
    font-size: 12px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  /* the explainer (via the ? button) still needs its own line when open */
  body.v2-shell .v2-topbar-compare .v2-topbar-inner:has(.v2-compare-explainer:not([hidden])) {
    flex-wrap: wrap;
  }

  /* ── 4. Page head (Results + every v2 tab): stack title over actions, and
     make the two action buttons an even full-width pair. ── */
  body.v2-shell .page-head {
    flex-direction: column;
    align-items: stretch;
    gap: 14px;
  }
  body.v2-shell .page-title { font-size: 24px; line-height: 1.2; }
  body.v2-shell .page-title small {
    display: block;
    margin: 6px 0 0;
    font-size: 12px;
    line-height: 1.5;
  }
  body.v2-shell .page-actions { display: flex; gap: 10px; }
  body.v2-shell .page-actions .btn {
    flex: 1 1 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    min-height: 44px;
  }
  /* the head-action icons ship with viewBox only — pin their box or they
     stretch to the flexed button's full width */
  body.v2-shell .page-actions .btn svg {
    width: 15px;
    height: 15px;
    flex: none;
  }

  /* ── 5. Section-jump pills (.lr-jump): the wrapping pile of pills becomes a
     single scrolling line, same interaction language as the product chips.
     (!important: the row ships inline flex-wrap:wrap from the renderer.)
     The soft edge is a mask, not a gradient — works on any background. ── */
  body.v2-shell .lr-jump {
    flex-wrap: nowrap !important;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
    -webkit-mask-image: linear-gradient(to left, transparent, #000 36px);
    mask-image: linear-gradient(to left, transparent, #000 36px);
    padding-right: 36px;
  }
  body.v2-shell .lr-jump::-webkit-scrollbar { display: none; }
  body.v2-shell .lr-jump-pill {
    white-space: nowrap;
    flex: none;
    min-height: 36px;
  }

  /* ── 6. Create-FAB: smaller footprint, clear of the content edge. ── */
  body.v2-shell .tc-create-fab {
    width: 48px;
    height: 48px;
    right: 14px;
    bottom: 14px;
  }

  /* ══ Round 3 — page BODY density (Daniel's device review round 2) ══
     Every metric grid is a `v2-mob-stack`; the GENERATED v2-theme.css collapses
     them all to ONE column on mobile via `.tab-content.v2-theme .v2-mob-stack
     { minmax(0,1fr) !important }` (0,3,0) — a giant near-empty card per tile.
     Rule of thumb here: KPI TILES pair up 2-across (a 96px donut or a
     number+sparkline doesn't earn a full-width card), while composed SECTIONS
     inside a stack keep the full row. Selectors carry `.tab-content` to TIE the
     theme rule's specificity — this file loads later, so it wins the tie. ── */
  body.v2-shell .tab-content .v2-mob-stack {
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
    gap: 10px !important;
  }
  body.v2-shell .tab-content .v2-mob-stack > :not(.kpi-tile) { grid-column: 1 / -1; }
  /* odd tile out (5-tile KPI strips) takes the full last row — no orphan hole */
  body.v2-shell .tab-content .v2-mob-stack > .kpi-tile:last-child:nth-child(odd) { grid-column: 1 / -1; }
  body.v2-shell .tab-content .v2-mob-stack > .kpi-tile { padding: 14px !important; min-width: 0; }

  /* The radar earns the full width — and a taller box scales its SVG labels
     up with the viewBox (they're unreadable at the inline 150px). */
  body.v2-shell .tab-content .v2-mob-stack > .kpi-tile:has(svg[aria-label^="Performance radar"]) {
    grid-column: 1 / -1;
  }
  body.v2-shell .tab-content .kpi-tile svg[aria-label^="Performance radar"] {
    height: 210px !important;
  }

  /* Sections: reclaim horizontal room for content. */
  body.v2-shell .tab-content .section { padding: 18px 16px; }

  /* Growth stat tiles (#res-growth-mount) ship anonymous inline-styled divs —
     bridge until the P1 renderer pass: equal 2-up tiles, no ragged wrap. */
  body.v2-shell #res-growth-mount div[style*="min-width:128px"] {
    min-width: 0 !important;
    flex: 1 1 calc(50% - 6px) !important;
  }
}
@media (max-width: 480px) {
  body.v2-shell .tab-content .section { padding: 16px 14px; }
}

/* ══ P2 2026-07 — working tabs: wide tables + local heatmap (also hits
   audit-mode: /audit/<token> boots the same body.v2-shell). ══ */
@media (max-width: 768px) {
  /* ── 7. Wide tables (rank-table: keywords/insights/ai-visibility, 1100px
     min-width; data-table: audit/competitors/backlinks, 500px) already scroll
     inside their card — but with zero affordance: a chopped column is the only
     hint. Same soft right-edge fade as the chip row, and the identity column
     pins so horizontal scroll never loses the row's subject. ── */
  body.v2-shell .tab-content .rank-table-wrap,
  body.v2-shell .tab-content .table-wrap,
  body.v2-shell .tab-content .section-body:has(.data-table) {
    -webkit-mask-image: linear-gradient(to left, transparent, #000 32px);
    mask-image: linear-gradient(to left, transparent, #000 32px);
  }
  /* responsive.css turns EVERY v2 table into `display:block; overflow-x:auto`
     — that makes the table its own (never-scrolling) scroll container, so a
     sticky cell pins to the table instead of the wrap and never sticks. These
     two table classes have a real scroll wrap; give them table display back
     so the wrap is the one scrollport. */
  body.v2-shell .tab-content .rank-table,
  body.v2-shell .tab-content .data-table {
    display: table;
    overflow-x: visible;
  }
  /* rank-table only: auto layout ignores cell max-width and hands the keyword
     column ~2/3 of the pane (the 1100px min-width's surplus is distributed by
     content size) — fixed pins it at 44vw and splits the rest evenly, each
     cell ellipsizing. NOT applied to .data-table: its expandable sub-rows
     carry their own header cells that fixed layout (sized from row 1 alone)
     would crush, and its 500px min-width doesn't inflate the identity column. */
  body.v2-shell .tab-content .rank-table {
    table-layout: fixed;
  }
  body.v2-shell .tab-content .rank-table th:first-child {
    width: 44vw;
  }
  body.v2-shell .tab-content .rank-table th,
  body.v2-shell .tab-content .rank-table td {
    overflow: hidden;
    text-overflow: ellipsis;
  }
  body.v2-shell .tab-content .rank-table th:first-child,
  body.v2-shell .tab-content .rank-table td:first-child,
  body.v2-shell .tab-content .data-table th:first-child,
  body.v2-shell .tab-content .data-table td:first-child {
    position: sticky;
    left: 0;
    z-index: 2;
    background: var(--bg-card, #FFFFFF);
    box-shadow: 1px 0 0 var(--border, #E8EAED);
  }
  body.v2-shell .tab-content .rank-table thead th:first-child {
    background: var(--bg-card-soft, #F8F9FA);
  }
  /* favourite-row tint must ride along under the pinned cell (v2-theme paints
     it on the tr, which a solid sticky cell would otherwise cover) */
  body.v2-shell .tab-content .rank-table tbody tr.fav td:first-child {
    background: #FFF8E1;
  }

  /* ── 8. Local heatmap: the renderer ships the desktop two-panel grid as an
     INLINE style, so `minmax(0,1fr)` computes to 0px beside the fixed 280px
     sidebar — an invisible map on phones (responsive.css already tries this
     stack but can't beat an inline style without !important). Map on top,
     stats sidebar below. ── */
  body.v2-shell .tab-content .heatmap-layout {
    grid-template-columns: minmax(0, 1fr) !important;
  }
  body.v2-shell .tab-content #heatmap-map {
    height: 380px !important; /* the inline 500px is most of a phone viewport */
  }
}

/* ══ P3 2026-07 — long tail: overscroll surface, compare-view stack, touch
   motion. All 13 remaining tabs measured overflow-free at 390 (P0–P2 already
   carry them) — what's left is feel, not layout. ══ */
@media (max-width: 768px) {
  /* ── 9. iOS overscroll flash: the global body background is the DARK v1
     token (#0F1B2B), which shows past the document edges on rubber-band
     scroll inside an all-light UI. Every tab is v2-theme now, so a light
     body surface is safe — matched to the shell/login surface. Mobile-only
     so the 1440 golden captures stay byte-identical. ── */
  body.v2-shell {
    background: #F5F7FA;
  }
  /* index.html still ships the v1-era inline `color-scheme: dark` on <html>
     — dark native controls/scrollbars inside a light UI on phones.
     !important because only that outranks an inline style; mobile-scoped so
     desktop captures can't move. */
  html:has(body.v2-shell) {
    color-scheme: light !important;
  }
  /* Overlays own their scroll — no chaining through to the page behind. */
  body.v2-shell .audit-explainer-overlay,
  body.v2-shell .modal-backdrop {
    overscroll-behavior: contain;
  }

  /* ── 10. Geo-grid compare (vs-competitor + baseline-vs-current): the
     three-column you|vs|them grid gives each mini-map ~84px at 390 —
     unreadable. Stack them full-width with the arrow card between. Maps
     initialise at phone width on load, so Leaflet sizes correctly. ── */
  body.v2-shell .tab-content .baseline-vs-current {
    grid-template-columns: minmax(0, 1fr);
  }
  body.v2-shell .tab-content .compare-arrow {
    width: auto;
  }
  body.v2-shell .tab-content .compare-arrow .arrow-stack {
    padding: 8px 14px;
  }
  body.v2-shell .tab-content .compare-arrow .arrow-stack svg {
    transform: rotate(90deg); /* points down the stacked flow, not sideways */
  }

  /* ── 11. Touch feel: a quiet press state on every tappable chrome control.
     :active only (no new hover states — sticky-hover is the touch trap);
     ease-out per the motion spec, disabled for prefers-reduced-motion. ── */
  body.v2-shell .v2-product,
  body.v2-shell .lr-jump-pill,
  body.v2-shell .page-actions .btn,
  body.v2-shell .tc-create-fab,
  body.v2-shell .header-getstarted-cta,
  body.v2-shell .view-toggle button {
    transition: transform 160ms ease-out;
    -webkit-tap-highlight-color: transparent; /* the press state replaces the UA flash */
  }
  body.v2-shell .v2-product:active,
  body.v2-shell .lr-jump-pill:active,
  body.v2-shell .page-actions .btn:active,
  body.v2-shell .tc-create-fab:active,
  body.v2-shell .header-getstarted-cta:active,
  body.v2-shell .view-toggle button:active {
    transform: scale(0.98);
  }
}
@media (max-width: 768px) and (prefers-reduced-motion: reduce) {
  body.v2-shell .v2-product,
  body.v2-shell .lr-jump-pill,
  body.v2-shell .page-actions .btn,
  body.v2-shell .tc-create-fab,
  body.v2-shell .header-getstarted-cta,
  body.v2-shell .view-toggle button {
    transition: none;
  }
  body.v2-shell .v2-product:active,
  body.v2-shell .lr-jump-pill:active,
  body.v2-shell .page-actions .btn:active,
  body.v2-shell .tc-create-fab:active,
  body.v2-shell .header-getstarted-cta:active,
  body.v2-shell .view-toggle button:active {
    transform: none;
  }
}
