/* mobile.css — v07zz288
   ─────────────────────────────────────────────────────────────────────
   THE authoritative phone stylesheet. Loaded LAST, so it wins every
   cascade tie. Everything here is gated on body[data-ui-tier="s"] —
   ZERO effect on desktop / tablet.

   Core principle (Hugo): never scroll the whole app. The shell is a
   FIXED frame; the header + topbar stay put; only the inner content
   panel scrolls; nothing ever sits under the bottom tab bar. */

/* Individual floating nav buttons (~52px) + bottom gap (14px) + generous
   breathing room above the content so the panel never touches them. */
:root { --mtab-h: calc(98px + env(safe-area-inset-bottom, 0px)); }

/* ════════ FIXED SHELL — panel-only scroll ════════ */
body[data-ui-tier="s"] .app-shell { height: var(--app-vh, 100vh); overflow: hidden; }
body[data-ui-tier="s"] .main-content {
  height: calc(var(--app-vh, 100vh) - var(--mtab-h));
  min-height: 0; overflow: hidden;
  display: flex; flex-direction: column;
  padding: 4px 10px 0; gap: 8px;
  border-top-left-radius: 0; border-bottom-left-radius: 0;
}
/* The top region (header, topbar, toggle) is pinned; the active view
   fills the rest and scrolls internally. */
body[data-ui-tier="s"] .main-content > .project-header,
body[data-ui-tier="s"] .main-content > .tb-mobile,
body[data-ui-tier="s"] .main-content > .ov-mtoggle { flex: 0 0 auto; }
body[data-ui-tier="s"] .main-content > .split-row,
body[data-ui-tier="s"] .main-content > .ov-dashboard,
body[data-ui-tier="s"] .main-content > .shots-panel,
body[data-ui-tier="s"] .main-content > .view-page { flex: 1 1 auto; min-height: 0; }

/* Overview shotlist: the panel fills the gap; its list scrolls. */
body[data-ui-tier="s"] .split-row { display: flex; flex-direction: column; min-height: 0; gap: 0; flex: 1 1 auto; }
body[data-ui-tier="s"] .split-row > .shots-panel { flex: 1 1 auto; min-height: 0; }
body[data-ui-tier="s"] .shots-panel { display: flex; flex-direction: column; min-height: 0; height: 100%; }
body[data-ui-tier="s"] .shots-list { flex: 1 1 auto; min-height: 0; max-height: none; overflow-y: auto; -webkit-overflow-scrolling: touch; }

/* Generic view pages (Shots / Assets / Review / Schedule / …). Two shapes:
   • pages WITH a dedicated .vp-scroll child (Assets, Media): the page is a
     fixed column and the child scrolls (so .vp-tabs can stay pinned);
   • pages WITHOUT one (Schedule, Script, Reports, Todo, Notes): the page
     scrolls ITSELF.
   Default = scroll-self (also the safe fallback where :has() is absent —
   prevents content being clipped); :has() upgrades vp-scroll pages. */
body[data-ui-tier="s"] .view-page { min-height: 0; height: 100%; overflow-y: auto; -webkit-overflow-scrolling: touch; }
body[data-ui-tier="s"] .view-page:has(> .vp-scroll) { display: flex; flex-direction: column; overflow: hidden; }
body[data-ui-tier="s"] .view-page > .vp-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch; }
body[data-ui-tier="s"] .view-page > .vp-head { flex: 0 0 auto; }
body[data-ui-tier="s"] .view-page--scroll { overflow-y: auto; }

/* Category tab row (Assets / Media): the column-flex was shrinking it to a
   sliver (Hugo: "categories at top getting cropped"). Pin its height and
   make the full set swipe horizontally so every category is reachable.
   Two structures exist: Assets has .vp-tabs as a direct child of .view-page;
   Media nests it inside .vp-head — both must scroll (Hugo: "stops at Archival,
   can't see Historical Refs etc"). */
body[data-ui-tier="s"] .view-page > .vp-tabs,
body[data-ui-tier="s"] .view-page .vp-head .vp-tabs {
  flex: 0 0 auto; height: auto; min-height: 42px; width: 100%; max-width: 100%;
  flex-wrap: nowrap; align-items: center;
  overflow-x: auto; overflow-y: hidden;
  -webkit-overflow-scrolling: touch; scrollbar-width: none;
  -webkit-mask-image: none; mask-image: none;
}
body[data-ui-tier="s"] .vp-tabs::-webkit-scrollbar { display: none; }
body[data-ui-tier="s"] .vp-tab { flex: 0 0 auto; white-space: nowrap; }
/* .vp-head must let its tab child take the full width to scroll */
body[data-ui-tier="s"] .view-page .vp-head { min-width: 0; max-width: 100%; }

/* Review page (mobile): drop the "Other edit versions" strip so the video +
   comments get the full height (Hugo: notes were cropped/unviewable). */
body[data-ui-tier="s"] .review-other-versions { display: none; }

/* Schedule phase cards: a horizontal row of small cards (Hugo: 5 in a row).
   The desktop card has height:100% + overflow:hidden which COLLAPSED it to
   22px in a flex row — force height:auto + overflow:visible so the content
   (name/dates/amount) shows. */
body[data-ui-tier="s"] .phase-grid {
  display: flex; flex-wrap: nowrap; grid-template-columns: none; gap: 8px;
  align-items: stretch; height: auto !important;
  overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none;
}
body[data-ui-tier="s"] .phase-grid::-webkit-scrollbar { display: none; }
body[data-ui-tier="s"] .phase-card {
  flex: 0 0 150px; width: 150px; height: auto !important; min-height: 0;
  overflow: visible; padding: 12px 13px;
}
body[data-ui-tier="s"] .phase-card-name { font-size: var(--fs-14); }
body[data-ui-tier="s"] .phase-card-amt { font-size: var(--fs-18); }
body[data-ui-tier="s"] .phase-card-cap,
body[data-ui-tier="s"] .phase-card-list { display: none; }
/* Calendar (mobile, Hugo: "too tall, too much scroll"). The row height is driven
   by --cal-row-h on the .big-cal--overlay (both the .big-cal-grid AND the
   absolutely-positioned .big-cal-bars-layer read var(--cal-row-h,130px) inline,
   so setting the var here keeps cells + phase bars perfectly aligned). The old
   grid-auto-rows:60px was DEAD — the inline gridTemplateRows always won. ~66px →
   a 6-row month is ~430px not ~780px. */
body[data-ui-tier="s"] .big-cal--overlay { --cal-row-h: 66px; }
body[data-ui-tier="s"] .big-cal { padding: 10px 10px 14px; }
body[data-ui-tier="s"] .big-cal--overlay .big-cal-cell { min-height: 0; padding-bottom: 16px; }
body[data-ui-tier="s"] .big-cal-num { font-size: var(--fs-10); }
/* phase bars → thin colour stripes; the named phase cards below carry the labels
   (a ~50px-wide phone column can't fit a phase name). */
body[data-ui-tier="s"] .big-cal-bar { height: 6px; padding: 0; font-size: 0; border-radius: 3px; transform: translateY(calc(var(--lane, 0) * -8px)); }
body[data-ui-tier="s"] .big-cal-bar-label { display: none; }
/* event / milestone chips → small colour dots (truncated words were unreadable in
   the cramped column; tapping the cell still opens the event). */
body[data-ui-tier="s"] .big-cal-event { width: 7px; height: 7px; min-height: 0; padding: 0; font-size: 0; border-radius: 50%; overflow: hidden; align-self: flex-start; }
/* clear the floating bottom nav so the last milestone row isn't cropped (Hugo). */
body[data-ui-tier="s"] .schedule-view,
body[data-ui-tier="s"] .view-page.schedule-view { padding-bottom: 92px; }
/* Payment Milestones: each milestone row STACKS its columns (status/name/
   date/amount were a 4-col grid that cropped) */
body[data-ui-tier="s"] .phase-milestones { width: 100%; max-width: 100%; min-width: 0; }
body[data-ui-tier="s"] .sched-milestone {
  display: flex; flex-direction: column; gap: 6px; align-items: flex-start;
  grid-template-columns: none; padding: 12px 0;
}
body[data-ui-tier="s"] .sched-milestone-status { align-self: flex-start; flex-shrink: 0; }
body[data-ui-tier="s"] .sched-milestone-name,
body[data-ui-tier="s"] .sched-milestone-date,
body[data-ui-tier="s"] .sched-milestone-amt { width: 100%; min-width: 0; word-break: break-word; }

/* ════════ TOP BRAND BAR ════════ */
.phm-bar { display: none; }
body[data-ui-tier="s"] .phm-bar {
  display: flex; align-items: center; gap: 11px;
  padding: 2px 2px 2px;
}
body[data-ui-tier="s"] .phm-burger {
  display: flex; align-items: center; justify-content: center;
  width: 42px; height: 42px; border-radius: 13px; flex: 0 0 auto;
  background: color-mix(in srgb, var(--shade-43) 55%, transparent); color: var(--ink-cream-4);
  border: 1px solid color-mix(in srgb, var(--ink-on-accent) 25%, transparent);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  cursor: pointer;
}
body[data-ui-tier="s"] .phm-word {
  font-family: var(--font-display, "Bebas Neue", sans-serif);
  font-size: var(--fs-22); letter-spacing: var(--track-08); color: var(--ink-cream-7);
}
/* Bell + avatar (+ search) align on the brand-bar line. Sync + scale
   dropped on mobile; search KEPT (Hugo). */
body[data-ui-tier="s"] .ph-right { position: absolute; top: 4px; right: 10px; display: flex; align-items: center; gap: 8px; }
body[data-ui-tier="s"] .ph-right .ph-scale-anchor,
body[data-ui-tier="s"] .ph-right .ph-iconbtn[aria-label="Refresh now"] { display: none; }
body[data-ui-tier="s"] .ph-right .ph-search-anchor { display: block; }

/* Project block: COLUMN under the brand bar, big bright title, tight.
   Drop the "PROJECT" eyebrow + status pill on a phone — the title carries
   the identity. Keep the compact subtitle + episode line. */
body[data-ui-tier="s"] .project-header {
  position: relative; padding: 0 0 2px;
  display: flex; flex-direction: column; align-items: stretch;
}
body[data-ui-tier="s"] .ph-left { width: 100%; max-width: none; opacity: 1; margin-top: 2px; }
body[data-ui-tier="s"] .ph-eyebrow { display: none; }
/* BIG title — fill the width up top (Hugo: take advantage of the space) */
body[data-ui-tier="s"] .ph-title { font-size: 66px; line-height: 0.8; color: var(--ink-cream-7); opacity: 1; }
body[data-ui-tier="s"] .ph-title-row { margin: 1px 0; width: 100%; }
body[data-ui-tier="s"] .ph-meta { font-size: var(--fs-11-5); gap: 5px; flex-wrap: wrap; margin-top: 3px; }
body[data-ui-tier="s"] .ph-status-pill { display: none; }
/* the title block was shrink-to-content (~278px), leaving the right third
   empty + cramping the title. Make it fill the header. */
/* margin:0 cancels the inherited desktop margin (-4px 20% 0 -16px) so the
   switcher + open panel LEFT-ALIGN with the page content below (Hugo). */
body[data-ui-tier="s"] .ph-project { width: 100%; position: relative; margin: 0; }
body[data-ui-tier="s"] .ph-title-row { width: 100%; }
/* switcher dropdown stays IN-FLOW (desktop display:grid 0fr→1fr) so opening it
   PUSHES the overview card + everything below DOWN instead of overlaying them
   (Hugo: "opening the switcher does not push everything down anymore"). The old
   position:absolute pulled it out of flow — that was the regression. */
body[data-ui-tier="s"] .ph-project-others { width: 100%; max-width: none; }
body[data-ui-tier="s"] .ph-project-others-inner { width: 100%; max-width: none; }
/* On Shots / Assets / Review / … collapse the title block entirely — the
   brand bar stays, the page reclaims the space. */
body[data-ui-tier="s"] .project-header.phm-collapsed .ph-left { display: none; }
body[data-ui-tier="s"] .project-header.phm-collapsed { padding-bottom: 0; }

/* ════════ TOPBAR — TRANSPARENT frosted glass (Hugo) ════════
   The forest backdrop must show through. A subtle STRAIGHT (horizontal)
   translucent gradient gives a faint donut→stats tonal shift WITHOUT a solid
   fill covering the text. No dark halo behind the donut. */
/* v07zz286 — REVAMPED overview bar. Three bands stacked: HERO (dominant donut
   + 2×2 stats), MODES (flush segmented icon row), TIMELINE (full-width schedule
   bar at the very bottom). Replaces the old cramped donut-left grid. */
body[data-ui-tier="s"] .topbar.tb-mobile {
  display: flex; flex-direction: column; gap: 9px;
  height: auto; padding: 12px 13px 11px; overflow: hidden;
  background: linear-gradient(90deg, color-mix(in srgb, var(--shade-44) 50%, transparent) 0%, color-mix(in srgb, var(--shade-45) 38%, transparent) 48%, color-mix(in srgb, color-mix(in srgb, var(--pale-green) 24%, var(--mix-dark)) 28%, transparent) 100%);
  border: 1px solid color-mix(in srgb, var(--ink-on-accent) 16%, transparent);
  backdrop-filter: blur(18px) saturate(1.08);
  -webkit-backdrop-filter: blur(18px) saturate(1.08);
  border-radius: 18px;
  box-shadow: 0 10px 26px color-mix(in srgb, var(--shade-46) 30%, transparent);
}
body[data-ui-tier="s"] .topbar.tb-mobile::after,
body[data-ui-tier="s"] .topbar.tb-mobile::before { display: none; }

/* ── HERO band: big donut (major feature) on the left, 2×2 stats on the right ── */
.tbm2-hero { display: grid; grid-template-columns: 150px minmax(0, 1fr); gap: 10px; align-items: center; }
.tbm2-donut { position: relative; display: grid; place-items: center;
  filter: drop-shadow(0 3px 12px color-mix(in srgb, var(--shade-46) 45%, transparent)); }
.tbm2-donut .tbm2-darken { display: none; }
.tbm2-ringlabel { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: 70%; display: flex; flex-direction: column; align-items: center; gap: 1px;
  text-align: center; pointer-events: none; }
.tbm2-ring-eyebrow { font-size: 8px; font-weight: var(--fw-bold); letter-spacing: 0.13em; text-transform: uppercase; color: color-mix(in srgb, var(--ink-cream-9) 82%, transparent); }
.tbm2-ring-pct { font-family: var(--font-display); font-size: var(--fs-38); line-height: 1; color: var(--ink-on-accent); font-feature-settings: var(--tnum); }
.tbm2-ring-pct span { font-size: var(--fs-18); opacity: 0.75; }
.tbm2-ring-sub { font-size: var(--fs-9); color: color-mix(in srgb, var(--ink-cream-9) 70%, transparent); margin-top: 1px; }

/* ── 2×2 stat tiles ── */
.tbm2-stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 5px 6px; min-width: 0; }
.tbm2-stat {
  display: flex; align-items: center; gap: 7px; min-width: 0;
  padding: 4px 5px; border: 0; background: transparent; cursor: pointer; text-align: left;
  border-radius: var(--r-panel); transition: background var(--dur-2) ease, opacity var(--dur-2) ease, box-shadow var(--dur-2) ease;
}
.tbm2-stat .tbm2-stat-chip { width: 28px; height: 28px; flex: 0 0 28px; transform: none; }
.tbm2-stat .tbm2-stat-chip svg { width: 16px; height: 16px; }
.tbm2-stat-body { min-width: 0; display: flex; flex-direction: column; gap: 0; }
.tbm2-stat-label { font-size: 8px; font-weight: var(--fw-bold); letter-spacing: var(--track-06); text-transform: uppercase; color: color-mix(in srgb, var(--ink-cream-9) 66%, transparent); line-height: 1.25; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tbm2-stat-val { font-family: var(--font-display); font-size: var(--fs-24); line-height: 1; color: var(--ink-on-accent); font-feature-settings: var(--tnum); }
.tbm2-stat.is-active { background: color-mix(in srgb, var(--hi) 16%, transparent); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--nav-active) 55%, transparent); }
.tbm2-stat.is-dimmed { opacity: 0.42; }

/* ── MODES band: ICON-ONLY compact segmented row (Hugo: smaller icons, no text
   to save space), gold active state ── */
.tbm2-modes { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 2px;
  padding: 2px; border-radius: 11px; background: color-mix(in srgb, var(--black) 22%, transparent);
  border: 1px solid color-mix(in srgb, var(--ink-on-accent) 7%, transparent); }
.tbm2-mode { display: flex; align-items: center; justify-content: center;
  font: inherit; color: color-mix(in srgb, var(--ink-cream-9) 58%, transparent); padding: 5px 0; border: 0; border-radius: var(--r-sm);
  background: transparent; cursor: pointer; min-width: 0;
  transition: background var(--dur-2) ease, color var(--dur-2) ease, box-shadow var(--dur-2) ease; }
.tbm2-mode-ico { display: inline-flex; }
.tbm2-mode-ico svg { width: 15px; height: 15px; stroke: currentColor; }
.tbm2-mode-lbl { display: none; }
.tbm2-mode.is-active { color: var(--nav-active); background: color-mix(in srgb, var(--shade-14) 60%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--nav-active) 75%, transparent); }

/* ── TIMELINE band: schedule bar at the bottom ──
   The base .tb-progress adds margin-left:12px + width:calc(100%-12px); our old
   width:100% override kept that 12px margin so the bar overflowed the RIGHT edge
   AND sat 12px right of the dates. Reset margin to 0 + width 100% so it (a) stays
   inside the card padding on BOTH sides and (b) left-aligns with the dates row.
   Track is heavily FADED (Hugo: empty bar gradient too opaque, cream showing at
   the far right) so the forest shows through the untravelled portion. */
.tbm2-timeline { display: flex; flex-direction: column; gap: 9px; }
.tbm2-timeline .tb-progress {
  margin-left: 0 !important; width: 100% !important; height: 8px;
  background: linear-gradient(180deg, color-mix(in srgb, color-mix(in srgb, var(--foil) 55%, var(--mix-light)) 26%, transparent), color-mix(in srgb, color-mix(in srgb, var(--ink-on-dark) 89%, var(--mix-dark)) 30%, transparent)) !important;
  border-color: color-mix(in srgb, var(--card-border) 35%, transparent) !important;
  overflow: visible;
}
/* fill uses the desktop --tb-fill-pct stretch trick: the green→gold gradient is
   stretched across the FULL bar width, so the filled portion only ever shows the
   green→mid slice up to the elapsed point and NEVER terminates in cream (Hugo:
   "at the extreme right side we still have cream colour"). */
.tbm2-timeline .tb-progress-fill-bar {
  background: linear-gradient(to right, var(--leaf-deep) 0%, var(--leaf) 50%, var(--gold-18) 100%) !important;
  background-size: calc(100% * 100 / var(--tb-fill-pct, 100)) 100% !important;
  background-position: left center !important;
  background-repeat: no-repeat !important;
}
/* single gold current-day chevron sitting just under the bar */
.tbm2-tl-marker { position: absolute; top: calc(100% + 1px); transform: translateX(-50%);
  color: var(--nav-active); pointer-events: none; z-index: 3; display: block; filter: drop-shadow(0 1px 1px color-mix(in srgb, var(--shade-42) 50%, transparent)); }
.tbm2-tl-marker svg { display: block; }
.tbm2-timeline-meta { display: flex; align-items: center; gap: 8px; font-size: var(--fs-10-5); color: color-mix(in srgb, var(--ink-cream-9) 80%, transparent); flex-wrap: nowrap; white-space: nowrap; min-width: 0; }
.tbm2-tl-dates { font-weight: var(--fw-bold); color: var(--ink-cream-7); overflow: hidden; text-overflow: ellipsis; }
.tbm2-tl-days { color: color-mix(in srgb, var(--ink-cream-9) 58%, transparent); }
.tbm-presence { display: inline-flex; align-items: center; transform: scale(0.82); transform-origin: right center; margin-left: auto; }

/* ════════ OVERVIEW Shotlist ⇄ Dashboard toggle ════════ */
.ov-mtoggle { display: flex; gap: 3px; padding: 3px; border-radius: var(--r-md); background: color-mix(in srgb, var(--shade-43) 42%, transparent); border: 1px solid color-mix(in srgb, var(--ink-on-accent) 12%, transparent); }
.ov-mtab { flex: 1 1 0; font: inherit; font-size: var(--fs-13); font-weight: var(--fw-semi); color: color-mix(in srgb, var(--ink-cream-4) 70%, transparent); padding: 8px; border: 0; border-radius: var(--r-9); background: transparent; cursor: pointer; }
.ov-mtab.is-active { background: color-mix(in srgb, var(--leaf) 22%, transparent); color: color-mix(in srgb, var(--leaf-bright) 29%, var(--mix-light)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--leaf) 30%, transparent); }
/* Dashboard: 2×2 grid (Hugo: panels were too wide + all stacked) */
/* ONE 2-col grid for the whole dashboard. The zones (.right-column /
   .footer-row) and their per-card .sortable-panel wrappers are flattened with
   display:contents so every card becomes a direct grid item — dense packing
   fills the cells with no empty bottom-right gap (Hugo). schedule + shot-queue
   span full width; the rest are half-cells. */
/* SINGLE-COLUMN stack — robust, never overlaps.
   The zone wrappers (.right-column / .footer-row) collapse to a 0-height box on
   mobile (their desktop flex/grid sizing resolves to 0 inside the ov-dashboard
   flex column), so their cards overflowed and overlapped everything below
   (Hugo: "completely broken, panels on top of each other"). The fix is to take
   the wrappers OUT of the box tree with display:contents — every card then
   becomes a direct flex child of .ov-dashboard and stacks cleanly with the gap.
   shot-breakdown-card is display:none (below), shot-queue-card is already a
   direct child. */
.ov-dashboard {
  display: flex; flex-direction: column; gap: 10px;
  overflow-y: auto; -webkit-overflow-scrolling: touch; padding-bottom: 8px;
}
.ov-dashboard .right-column,
.ov-dashboard .footer-row,
.ov-dashboard .sortable-panel {
  display: contents !important;
}
.ov-dashboard .rc-card,
.ov-dashboard > .sb-queue {
  min-width: 0; width: 100% !important; position: relative !important; transform: none !important;
  margin: 0 !important; box-shadow: 0 4px 14px color-mix(in srgb, var(--shade-41) 18%, transparent);
  /* Promoted to direct flex-children of the height-capped ov-dashboard column —
     stop them from flex-shrinking to a sliver; keep natural height + let the
     dashboard scroll. */
  flex: 0 0 auto !important; height: auto !important; min-height: 0 !important; max-height: none !important;
}
/* The Shot Queue card is the desktop sidebar card (.sb-queue, glass-dark) —
   give it the same rounded glass treatment as the other dashboard cards. */
.ov-dashboard > .sb-queue { border-radius: 15px; cursor: pointer; }

/* Overview SEQUENCES sub-tab: small 2-col grid (was giant cards) */
body[data-ui-tier="s"] .sequences-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
body[data-ui-tier="s"] .sequence-card { min-height: 0; }
/* Overview ASSETS sub-tab: keep card aspect ratios (Hugo: character cards are
   4:5 portrait, not square); props are smaller so they don't hog space. */
body[data-ui-tier="s"] .assets-overview .character-card--h,
body[data-ui-tier="s"] .assets-overview .location-card--h,
body[data-ui-tier="s"] .assets-overview .animal-card--h,
body[data-ui-tier="s"] .assets-overview .prop-card--h { height: auto; }
/* character: 4:5 portrait thumb */
body[data-ui-tier="s"] .assets-overview .character-card--h { width: 132px; }
body[data-ui-tier="s"] .assets-overview .character-thumb { height: auto; aspect-ratio: 4 / 5; }
/* locations/animals: landscape thumbs */
body[data-ui-tier="s"] .assets-overview .location-thumb,
body[data-ui-tier="s"] .assets-overview .animal-thumb { height: 92px; }
/* props: compact */
body[data-ui-tier="s"] .assets-overview .prop-card--h { width: 120px; }
body[data-ui-tier="s"] .assets-overview .prop-thumb { height: 78px; }

/* ════════ PANEL RADIUS — smaller on a phone (Hugo: the big radius ate the
   Shots/Sequences eyebrow tabs and clashed with the button radii). ════════ */
body[data-ui-tier="s"] .shots-panel.glass,
body[data-ui-tier="s"] .view-page.glass,
body[data-ui-tier="s"] .ov-dashboard .glass,
body[data-ui-tier="s"] .split-row .glass { border-radius: 15px; }

/* ════════ SHOT ROWS — big thumb · id+title+status · big ring ════════ */
body[data-ui-tier="s"] .shots-panel.glass { padding: 0 4px; }
body[data-ui-tier="s"] .shots-header { padding: 10px 12px 6px; }
/* big thumbnail · shot id (big) + italic subtle title + status pill · the
   donut ring fills the whole right cell (Hugo). Drop sequence eyebrow, lens
   line, location, version text and the quick-action strip. */
body[data-ui-tier="s"] .shot-row,
body[data-ui-tier="s"][data-thumbsize] .shot-row {
  --row-thumb-w: 124px;
  position: relative;
  grid-template-columns: var(--row-thumb-w) minmax(0, 1fr) auto;
  column-gap: 11px; align-items: center;
  padding: 7px 14px 7px 8px;
}
body[data-ui-tier="s"] .shot-thumb,
body[data-ui-tier="s"][data-thumbsize] .shot-thumb { width: 132px; }
body[data-ui-tier="s"] .shot-eyebrow,
body[data-ui-tier="s"] .shot-sub,
body[data-ui-tier="s"] .shot-loc,
body[data-ui-tier="s"] .shot-version,
body[data-ui-tier="s"] .shot-quick-actions { display: none; }
/* shot # big, title italic + subtle, inline on the same row */
body[data-ui-tier="s"] .shot-info { gap: 2px; padding-bottom: 0; }
body[data-ui-tier="s"] .shot-title { white-space: normal; display: flex; flex-wrap: wrap; align-items: baseline; gap: 3px 8px; }
body[data-ui-tier="s"] .shot-id { font-size: 21px; font-weight: var(--fw-bold); letter-spacing: var(--track-01); }
body[data-ui-tier="s"] .shot-dot { display: none; }
body[data-ui-tier="s"] .shot-frame { font-size: var(--fs-13); font-style: italic; font-weight: 400; opacity: 0.6; }
body[data-ui-tier="s"] .shot-thumb,
body[data-ui-tier="s"][data-thumbsize] .shot-thumb { width: 124px; }
/* right cluster: status pill THEN the donut ring, side by side, vertically
   centred (Hugo: status to the left of the donut, all row-aligned) */
body[data-ui-tier="s"] .shot-right { display: flex; flex-direction: row; align-items: center; justify-content: flex-end; gap: 10px; }
body[data-ui-tier="s"] .shot-right-text { position: static; margin: 0; display: flex; align-items: center; }
body[data-ui-tier="s"] .shot-right-pill { margin: 0; }
body[data-ui-tier="s"] .shot-right-ring { width: 54px; height: 54px; flex: 0 0 54px; }
body[data-ui-tier="s"] .shot-right-ring .pring { width: 54px; height: 54px; }

/* ════════ DRAWER — fit without scroll ════════ */
body[data-ui-tier="s"] .sidebar { overflow: hidden; padding: 14px 10px 10px; }
body[data-ui-tier="s"] .sidebar .nav-list { gap: 0; padding: 4px 0; }
body[data-ui-tier="s"] .sidebar .nav-item { padding: 9px 12px; gap: 12px; }
body[data-ui-tier="s"] .sidebar .nav-icon svg { width: 19px; height: 19px; }
body[data-ui-tier="s"] .sidebar .nav-label { font-size: var(--fs-14); }
/* the dashboard-y bottom zone (project day / pipeline / shot queue) lives
   on the Overview dashboard now — hidden in the drawer so nothing scrolls */
body[data-ui-tier="s"] .sidebar .sidebar-footer { display: none; }
body[data-ui-tier="s"] .sidebar .sidebar-spacer { flex: 0 0 0; }

/* ════════ BOTTOM TAB BAR ════════ */
/* INDIVIDUAL floating buttons — no container bar (Hugo). Each tab is its own
   glass pill floating over the app; the panel content runs all the way to the
   bottom behind them. The bar itself is click-through (pointer-events:none)
   so only the pills capture taps. */
.mtab-bar {
  position: fixed; left: 0; right: 0; bottom: calc(14px + env(safe-area-inset-bottom, 0px));
  z-index: var(--z-mobile-nav); pointer-events: none;
  display: flex; align-items: center; justify-content: center; gap: 9px;
  padding: 0 12px;
}
.mtab {
  pointer-events: auto;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  width: 67px; padding: 8px 6px 6px;
  background: color-mix(in srgb, var(--shade-14) 55%, transparent);
  border: 1px solid color-mix(in srgb, var(--ink-on-accent) 14%, transparent);
  border-radius: 13px;
  backdrop-filter: blur(16px) saturate(1.2);
  -webkit-backdrop-filter: blur(16px) saturate(1.2);
  box-shadow: 0 8px 20px color-mix(in srgb, var(--shade-42) 36%, transparent);
  color: color-mix(in srgb, var(--ink-cream-4) 66%, transparent); cursor: pointer;
  font-family: var(--font-body);
  transition: color 160ms ease, background 160ms ease, box-shadow 160ms ease, transform 160ms ease;
}
.mtab-icon { display: flex; }
.mtab-icon svg { width: 22px; height: 22px; }
.mtab-label { font-size: var(--fs-9-5); font-weight: var(--fw-semi); letter-spacing: var(--track-02); white-space: nowrap; }
/* selected = GOLD OUTLINE on the icon, no solid green fill (Hugo) */
.mtab.is-active {
  color: var(--nav-active);
  background: color-mix(in srgb, var(--shade-14) 62%, transparent);
  border-color: color-mix(in srgb, var(--nav-active) 85%, transparent);
  box-shadow: 0 8px 22px color-mix(in srgb, var(--shade-42) 40%, transparent), inset 0 0 0 1px color-mix(in srgb, var(--nav-active) 40%, transparent);
}
.mtab.is-active .mtab-icon svg { stroke: var(--nav-active); }

/* ════════ MODALS — floating padded panels (Hugo: pop-up, not full-bleed) ════════
   A ~10px gap all round + a real radius makes them read as a modal that sits
   on top of the app, rather than a full-screen takeover. The ASSET modal uses
   its own .char-modal-backdrop which had 32px padding (desktop) — that pushed
   the 370px card off-centre and over the right edge. Zero it so margin:auto
   centres the card. */
body[data-ui-tier="s"] .modal-backdrop { padding: 0; }
body[data-ui-tier="s"] .char-modal-backdrop { padding: 0; }
body[data-ui-tier="s"] .modal-card,
body[data-ui-tier="s"] .char-modal {
  width: calc(100vw - 20px); max-width: calc(100vw - 20px);
  height: calc(var(--app-vh, 100vh) - 20px); max-height: calc(var(--app-vh, 100vh) - 20px);
  margin: 10px auto; border-radius: 22px;
  box-shadow: 0 24px 64px color-mix(in srgb, var(--shade-42) 58%, transparent);
}
body[data-ui-tier="s"] .char-modal-nav { display: none; }

/* ── ASSET MODAL (mobile) — same treatment as the shot modal ───────────
   Big image sticky at the top, compact info scrolling beneath, clean button
   placement (was off-centre with buttons everywhere). */
body[data-ui-tier="s"] .char-modal { position: relative; display: flex; flex-direction: column; overflow-x: hidden; overflow-y: auto; -webkit-overflow-scrolling: touch; touch-action: pan-y; }
body[data-ui-tier="s"] .char-modal-grid {
  display: flex; flex-direction: column;
  grid-template-columns: none; height: auto; gap: 0; flex: 0 0 auto;
}
/* hero image: inset from the edges (Hugo: too tight) + fully rounded corners,
   a touch shorter so there's less to scroll past */
body[data-ui-tier="s"] .char-media { width: 100%; height: auto; min-width: 0; padding: 12px 12px 4px; margin: 0; position: sticky; top: 0; z-index: 6; background: var(--paper, var(--ink-on-accent)); }
body[data-ui-tier="s"] .char-main-img {
  width: 100%; height: 36vh; min-height: 210px; max-height: 40vh;
  object-fit: cover; border-radius: 16px;
  box-shadow: 0 12px 22px -8px color-mix(in srgb, var(--shade-41) 50%, transparent);
}
body[data-ui-tier="s"] .char-info {
  width: 100%; max-width: none; min-width: 0;
  padding: 10px 16px 16px; gap: 10px; background: var(--paper, var(--ink-on-accent));
}
/* SHOTS · REF PASSES · LOCKED on a single 3-col row (Hugo) */
body[data-ui-tier="s"] .char-stats-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; }
body[data-ui-tier="s"] .char-gallery-wrap { width: 100%; min-width: 0; flex: 0 0 auto; padding: 0 12px 14px; background: var(--paper, var(--ink-on-accent)); }
/* action buttons absolute over the image's top corners — clean, no centred
   pill (Hugo: buttons all over the place). Generate becomes a small round
   sparkle icon next to the close button. */
body[data-ui-tier="s"] .char-modal-close,
body[data-ui-tier="s"] .char-modal-edit,
body[data-ui-tier="s"] .char-modal-archive { position: absolute; z-index: 11; }
body[data-ui-tier="s"] .char-modal-close { top: 16px; right: 16px; transform: none; left: auto; }
body[data-ui-tier="s"] .char-modal-edit { top: 16px; left: 16px; }
body[data-ui-tier="s"] .char-modal-archive { top: 16px; left: 54px; }
/* Generate button removed from the asset modal for now (Hugo) */
body[data-ui-tier="s"] .char-modal-generate { display: none; }
/* notes drawer = full-width overlay; fixed so its off-canvas state can't add
   horizontal scroll */
body[data-ui-tier="s"] .char-notes-drawer { position: fixed; inset: 0; width: 100vw; max-width: 100vw; z-index: 12; }

/* v07zz287 — ROLE IN STORY lifted to the top sits right under the stats; tighten
   it so it doesn't add a big gap before VOICE/NOTES. */
body[data-ui-tier="s"] .char-info .char-role-top { margin-top: 2px; }
/* inline NOTES panel (replaces Direction Presets on mobile) — deck-style list +
   composer. Cap the list so the composer + the rest of the column stay reachable
   without the whole modal ballooning. */
body[data-ui-tier="s"] .char-notes-inline { padding: 0; }
body[data-ui-tier="s"] .char-notes-inline .notes-panel { padding: 0; background: transparent; border: 0; }
body[data-ui-tier="s"] .char-notes-inline .notes-list { max-height: 34vh; overflow-y: auto; -webkit-overflow-scrolling: touch; }
/* STATUS control — match the shot modal's circle/dot stepper look (Hugo): drop
   the boxed pills, render each option as a prominent circle with a small label
   beneath, active one ringed gold. Reserve fixed height so toggling never shifts. */
body[data-ui-tier="s"] .asset-status-seg-row { display: flex; flex-wrap: nowrap; gap: 4px; justify-content: space-between; }
body[data-ui-tier="s"] .asset-status-seg-btn {
  flex: 1 1 0; min-width: 0; flex-direction: column; align-items: center; gap: 5px;
  border: 0 !important; background: transparent !important; padding: 4px 2px;
  font-size: 8px; font-weight: var(--fw-bold); letter-spacing: var(--track-02); text-transform: uppercase; text-align: center; line-height: 1.1;
}
body[data-ui-tier="s"] .asset-status-seg-btn .asset-status-dot {
  width: 20px; height: 20px; border-radius: 50%; flex: 0 0 20px;
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.45), inset 0 1px 1px rgba(255,255,255,0.4);
  transition: box-shadow var(--dur-2) ease;
}
body[data-ui-tier="s"] .asset-status-seg-btn.is-on .asset-status-dot {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--nav-active) 85%, transparent), inset 0 1px 1px rgba(255,255,255,0.5);
}
body[data-ui-tier="s"] .asset-status-seg-btn:not(.is-on) { opacity: 0.62; }
body[data-ui-tier="s"] .asset-status-seg-cap { font-size: 8px; }

/* ── SHOT MODAL (mobile) ────────────────────────────────────────────────
   Image sticky at the top so you can write a note while looking at it. Keep
   the FRAMES/VIDEO version strips (Hugo: critical) — only the EMPTY
   placeholder sections are hidden (so an empty VIDEO row vanishes until a
   video exists). Drop the prompt block, the Open-in-folder button and the
   hero expand button (no fullscreen on a phone). */
body[data-ui-tier="s"] .modal-card { position: relative; overflow-x: hidden; overflow-y: auto; -webkit-overflow-scrolling: touch; padding-top: 0; touch-action: pan-y; }
/* Compact header: shot # + italic title on ONE line, no sequence pill, less
   top waste so the FRAMES strip sits higher (Hugo). */
body[data-ui-tier="s"] .modal-card .modal-header { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 9px; padding: 14px 48px 6px 16px; }
body[data-ui-tier="s"] .md-id { font-size: var(--fs-30); display: inline-block; }   /* bigger shot # (Hugo) */
body[data-ui-tier="s"] .md-frame { font-size: var(--fs-14); font-style: italic; opacity: 0.62; display: inline-block; }
body[data-ui-tier="s"] .md-chip { display: none; }   /* drop the SEQUENCE pill */
body[data-ui-tier="s"] .md-vidpath-btn { display: none; }   /* v07zz535 — desktop/local-only action */
/* Generate button removed from the shot modal for now (Hugo) */
body[data-ui-tier="s"] .md-generate-pill { display: none; }
/* stage stepper (Hugo: "status phase circles going out of bound"). The desktop
   grid uses 56px-min steps + 18px lines → 7 stages = ~500px, way past the modal.
   On mobile, flip to a flex row where the CONNECTOR LINES flex to fill and the
   steps shrink to their (smaller) label, so all phases fit edge-to-edge inside
   the modal. overflow-x:auto stays as a safety net for unusually long chains. */
body[data-ui-tier="s"] .modal-card .pipeline-stepper {
  display: flex; align-items: flex-start; gap: 0;
  overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none;
}
body[data-ui-tier="s"] .modal-card .pipeline-stepper::-webkit-scrollbar { display: none; }
body[data-ui-tier="s"] .modal-card .pipeline-stepper .stepper-step { min-width: 0; flex: 0 1 auto; gap: 4px; }
body[data-ui-tier="s"] .modal-card .pipeline-stepper .stepper-line { flex: 1 1 auto; min-width: 6px; margin-top: -14px; }
body[data-ui-tier="s"] .modal-card .pipeline-stepper .step-circle { width: 18px; height: 18px; border-width: 1.5px; }
body[data-ui-tier="s"] .modal-card .pipeline-stepper .step-circle svg { width: 11px; height: 11px; }
body[data-ui-tier="s"] .modal-card .pipeline-stepper .step-label { font-size: var(--fs-7-5); line-height: 1.15; letter-spacing: -0.01em; }
body[data-ui-tier="s"] .modal-card .modal-hero-image {
  position: sticky; top: 0; z-index: 6; margin-top: 4px; border-radius: 16px;
  overflow: hidden;
  box-shadow: 0 12px 22px -8px color-mix(in srgb, var(--shade-41) 50%, transparent);
}
body[data-ui-tier="s"] .modal-card .modal-close-btn { position: absolute; top: 12px; right: 12px; z-index: 11; }
body[data-ui-tier="s"] .modal-card .prompt-block,
body[data-ui-tier="s"] .modal-card .mhi-expand-btn,
body[data-ui-tier="s"] .modal-card .meta-block,
body[data-ui-tier="s"] .reveal-folder-btn { display: none; }
/* tighten the in-between blocks so FRAMES + notes fit without scrolling */
body[data-ui-tier="s"] .modal-card .modal-action { padding: 8px 16px; font-size: var(--fs-13); }
body[data-ui-tier="s"] .modal-card .modal-vo { padding: 8px 16px; }
body[data-ui-tier="s"] .modal-card .pipeline-stepper { padding: 8px 14px; }
/* keep populated version strips; hide a row only when it has no real tiles.
   The real tiles live in a .version-scroller--overlay layer (the section
   always carries an empty placeholder too), so test for the overlay's
   absence — that's the genuinely-empty case (e.g. VIDEO before any render). */
body[data-ui-tier="s"] .modal-card .version-section:not(:has(.version-scroller--overlay)) { display: none; }
body[data-ui-tier="s"] .modal-card .version-section { padding-left: 16px; padding-right: 16px; }

/* ════════ ASSETS PAGE — 2-up card grids (Hugo) ════════ */
body[data-ui-tier="s"] .characters-grid,
body[data-ui-tier="s"] .animals-grid,
body[data-ui-tier="s"] .locations-grid,
body[data-ui-tier="s"] .props-grid {
  grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px;
}

/* ════════ REVIEW — notes column fills the height (Hugo: was cropped) ════════
   The comments scroller no longer caps short; it grows to fill and scrolls
   internally so the full thread is reachable above the Add-note button. */
/* cap (not force) the notes height so the "+ Add note" composer below stays
   on-screen (min-height:46vh was pushing it off the bottom) */
body[data-ui-tier="s"] .review-comments-scroll { max-height: 46vh; min-height: 0; flex: 0 1 auto; }
body[data-ui-tier="s"] .review-comments { max-height: none; }
body[data-ui-tier="s"] .review-side-composer { position: sticky; bottom: 0; z-index: 3; }

/* ════════ ADMIN PAGE — full mobile rework (Hugo) ════════
   Sections go full-width with tight padding; the two wide grids (user table +
   permissions matrix) scroll horizontally INSIDE their card; every other
   panel (invite form, diagnostic stats, integrations, api status, members)
   stacks to a single column so nothing bleeds off-screen. */
body[data-ui-tier="s"] .admin-view { padding: 0; gap: 12px; }
body[data-ui-tier="s"] .admin-section { padding: 14px 14px 12px; width: 100%; max-width: 100%; min-width: 0; }
body[data-ui-tier="s"] .admin-two-col { grid-template-columns: 1fr !important; gap: 10px; }
/* user table: keep the 7-col grid but scroll it within its card */
body[data-ui-tier="s"] .admin-table { display: block; width: 100%; max-width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }
body[data-ui-tier="s"] .admin-table-head,
body[data-ui-tier="s"] .admin-table-row { min-width: 640px; }
/* permissions matrix (inline grid-template-columns): keep it, scroll it */
body[data-ui-tier="s"] .admin-matrix { width: 100%; max-width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }
/* invite form → full-width stack */
body[data-ui-tier="s"] .admin-invite-grid { grid-template-columns: 1fr; gap: 8px; }
/* diagnostic stat row → vertical stack */
body[data-ui-tier="s"] .admin-diag-stats { flex-direction: column; gap: 10px; align-items: stretch; }
/* integrations + api status → single column */
body[data-ui-tier="s"] .admin-integrations { flex-direction: column; }
body[data-ui-tier="s"] .admin-integration { width: 100%; min-width: 0; }
body[data-ui-tier="s"] .api-status-grid { grid-template-columns: 1fr; }
body[data-ui-tier="s"] .api-status-detail { max-width: 48%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ════════ OVERVIEW DASHBOARD (mobile) ════════
   Drop the Shot Breakdown card (Hugo); the Shot Queue card is mounted here
   instead (App.jsx). Keep panel content from cropping at 2-col width. */
body[data-ui-tier="s"] .ov-dashboard .shot-breakdown-card { display: none; }
body[data-ui-tier="s"] .ov-dashboard .shot-queue-card { grid-column: 1 / -1; }
body[data-ui-tier="s"] .ov-dashboard .milestones-list { max-height: 240px; }
body[data-ui-tier="s"] .ov-dashboard .milestones-section { gap: 4px; }
body[data-ui-tier="s"] .ov-dashboard .thumb-row { grid-template-columns: repeat(auto-fit, minmax(78px, 1fr)); gap: 6px; }
body[data-ui-tier="s"] .ov-dashboard .activity-card,
body[data-ui-tier="s"] .ov-dashboard .media-card,
body[data-ui-tier="s"] .ov-dashboard .notes-card,
body[data-ui-tier="s"] .ov-dashboard .milestones-card { min-width: 0; }
body[data-ui-tier="s"] .ov-dashboard .activity-card *,
body[data-ui-tier="s"] .ov-dashboard .notes-card * { min-width: 0; word-break: break-word; }

/* ════════ PRESENTATION deck review (mobile) ════════
   Hugo: give the SLIDES more room (see ~2 at once) and pin the COMPOSER to the
   very bottom of the panel without shrinking it. The detail is a full-height
   flex column: the STAGE (slides) flex-grows to absorb all leftover height; the
   SIDE block is natural-height (capped comments list + fixed composer) and, as
   the last flex child, sits at the bottom — so the composer hugs the panel
   bottom. The old @media(max-width:1000px) gave the stage a fixed 60vh and the
   side 52vh, which starved the slides and floated the composer mid-panel. */
body[data-ui-tier="s"] .review-view { display: flex; flex-direction: column; min-height: 0; }
/* override the desktop .pdv-detail height:calc(100vh-285px) — on a phone it must
   simply FILL the view-page (between the project header and the bottom nav). */
body[data-ui-tier="s"] .pdv-detail { height: auto !important; min-height: 0; flex: 1 1 auto; padding-bottom: 0; }
body[data-ui-tier="s"] .pdv-detail-body { display: flex !important; flex-direction: column; height: auto; flex: 1 1 auto; min-height: 0; }
body[data-ui-tier="s"] .pdv-stage-col { flex: 1 1 auto !important; min-height: 0; height: auto !important; }
body[data-ui-tier="s"] .pdv-slides-scroll { -webkit-overflow-scrolling: touch; }
body[data-ui-tier="s"] .pdv-side { flex: 0 0 auto !important; height: auto !important; max-height: 46vh !important; min-height: 0; }
/* hide the chunky "Review mode — click any image…" description so the deck head
   is as compact as the Edits head (reclaims ~140px for the slides). */
body[data-ui-tier="s"] .pdv-detail .review-detail-sub { display: none; }
/* comments list capped SMALL so the composer keeps its full size AND the slides
   get ~2-slide height; the list scrolls internally for the rest (Hugo). */
body[data-ui-tier="s"] .pdv-side .review-comments-scroll { max-height: 17vh; min-height: 48px; flex: 1 1 auto; }
body[data-ui-tier="s"] .pdv-composer { flex: 0 0 auto; position: sticky; bottom: 0; z-index: 3; }
