/* ============================================================================
   LightVision mobile web layout (phones / narrow web viewports).

   Loaded AFTER styles.css. Every rule lives inside ONE media query and is
   scoped under html.lv-web (stamped pre-paint by the web adapter), so desktop
   web >840px and Electron (which never gets .lv-web) are pixel-unchanged.

   Companion behavior lives in mobile-ui.js (Agent B): it creates #lvMobileNav,
   #lvMenuBtn, #lvScrim, #lvMenuSheet, #lvSearchSheet, #lvSheetHandle and
   #lvCullEdit, and toggles html.lv-mobile / html.lv-mnav / body.lv-drawer-open
   / html.lv-sheet-tall. When inactive, that chrome carries [hidden]
   (styles.css [hidden] { display:none !important } keeps it invisible at any
   viewport width).

   Z-index ladder (slots between the existing nav pill 45 and overlays 1100+):
   bottom nav 1050 - editor sheet 1000 - drawer scrim 1490 - drawer 1500 -
   sheet scrims 1590 - menu/search sheets 1600.
   ========================================================================== */

@media (max-width: 840px) {

  /* --------------------------------------------------------------------------
     0. Sheet-height token. mobile-ui.js sets --lv-sheet-h inline on <html>
        during handle drags (inline style wins over these), and clears it on
        release so these stops rule: default 46dvh, tall 82dvh.
     ------------------------------------------------------------------------ */
  html.lv-web {
    --lv-sheet-h: 46dvh;
  }
  /* Tall is capped so a slice of the photo ALWAYS stays visible — 82dvh left
     zero image on phones whose browser chrome eats ~160px (Samsung Internet). */
  html.lv-web.lv-sheet-tall {
    --lv-sheet-h: 72dvh;
  }
  /* In tall mode the filmstrip yields its row to the photo. */
  html.lv-web.lv-sheet-tall .app-shell.editor-open .editor-filmstrip {
    display: none;
  }

  /* --------------------------------------------------------------------------
     1. Shell reset - collapse the fixed 260/1fr/360 desktop grid (styles.css
        :663) into a single scrolling column. dvh dodges the iOS URL-bar trap.
     ------------------------------------------------------------------------ */
  html.lv-web body {
    min-width: 0;
    min-height: 0;
    /* Android Chrome pull-to-refresh would hijack swipe-down (= reject in the
       cull reviewer) and glass-swipes near the top of any scroller. */
    overscroll-behavior: none;
  }

  html.lv-web .photo-grid,
  html.lv-web .develop-scroll,
  html.lv-web aside.sidebar {
    overscroll-behavior: contain;
  }

  html.lv-web .app-shell {
    display: block;
    height: 100dvh;
    overflow: hidden;
  }

  html.lv-web .workspace {
    height: 100%;
    min-width: 0;
  }

  /* --------------------------------------------------------------------------
     2. Sidebar becomes a left drawer. The extra .app-shell in the selector
        out-specifies .app-shell.sidebar-collapsed .sidebar (styles.css
        :697-703), so the collapsed-state fade can never strand the drawer
        invisible.
     ------------------------------------------------------------------------ */
  html.lv-web .app-shell aside.sidebar {
    position: fixed;
    top: 0;
    left: 0;
    height: 100dvh;
    width: min(320px, 86vw);
    z-index: 1500;
    transform: translateX(-105%);
    transition: transform 0.28s ease;
    overflow-y: auto;
    opacity: 1;
    pointer-events: auto;
    padding: 14px;
    /* Clearance for the web adapter's account chip, which pins bottom-left
       with `padding-bottom: 88px !important` - match its priority. */
    padding-bottom: calc(88px + env(safe-area-inset-bottom, 0px)) !important;
    border-right: 1px solid var(--line);
    box-shadow: 0 0 60px rgba(0, 0, 0, 0.55);
  }

  html.lv-web body.lv-drawer-open aside.sidebar {
    transform: translateX(0);
  }

  html.lv-web #lvScrim {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.5);
    z-index: 1490;
  }

  /* Desktop collapse/reveal affordances make no sense with a drawer. */
  html.lv-web #sidebarCollapseBtn,
  html.lv-web #sidebarRevealBtn {
    display: none !important;
  }

  /* --------------------------------------------------------------------------
     3. Header - one compact row: hamburger + truncating folder/status labels.
        The floating fixed nav pill (styles.css :1400, editor shrink :1477)
        is replaced by the bottom nav.
     ------------------------------------------------------------------------ */
  html.lv-web header.toolbar {
    min-height: 0;
    padding: 8px 10px 8px;
    justify-content: flex-start;
    gap: 8px;
  }

  html.lv-web header.toolbar .toolbar-title {
    display: block;
    flex: 1 1 auto;
    min-width: 0;
  }

  html.lv-web header.toolbar #folderLabel,
  html.lv-web header.toolbar #statusLabel {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
  }

  html.lv-web header.toolbar #statusLabel {
    font-size: 14px;
    margin: 0;
  }

  html.lv-web .toolbar-actions {
    display: none;
  }

  /* Hamburger (mobile-ui.js injects as the toolbar's first child). */
  html.lv-web #lvMenuBtn {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    padding: 0;
    border: none;
    border-radius: 10px;
    background: transparent;
    color: var(--text);
    cursor: pointer;
  }
  html.lv-web #lvMenuBtn:active {
    background: var(--raised);
  }
  html.lv-web #lvMenuBtn svg {
    width: 24px;
    height: 24px;
    display: block;
  }

  /* --------------------------------------------------------------------------
     4. Grid toolbar - one horizontally scrollable row of touch-size controls.
        The bottom nav owns Cull; card-size and People coverage are desktop
        affordances.
     ------------------------------------------------------------------------ */
  html.lv-web #galleryToolbar {
    display: flex;
    flex-wrap: nowrap;
    justify-content: flex-start;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding: 8px 10px;
    gap: 8px;
  }
  html.lv-web #galleryToolbar::-webkit-scrollbar {
    display: none;
  }

  html.lv-web #galleryToolbar .gallery-toolbar-left,
  html.lv-web #galleryToolbar .gallery-toolbar-right,
  html.lv-web #galleryToolbar .selection-controls,
  html.lv-web #galleryToolbar .sort-control,
  html.lv-web #galleryToolbar .view-toggle {
    flex: 0 0 auto;
  }

  html.lv-web #galleryToolbar .tool-btn {
    height: auto;
    min-height: 40px;
  }

  html.lv-web #galleryToolbar .size-control,
  /* Cull lives in the bottom nav; People stays — identity clustering runs on
     phones now and the hub is a core mobile surface. */
  html.lv-web #galleryToolbar #cullStart {
    display: none;
  }

  /* --------------------------------------------------------------------------
     5. Photo grid - ~3 columns on a phone, always-visible selection check,
        bottom clearance for the fixed nav.
     ------------------------------------------------------------------------ */
  html.lv-web .photo-grid {
    grid-template-columns: repeat(auto-fill, minmax(108px, 1fr));
    gap: 6px;
    padding: 8px;
    padding-bottom: calc(76px + env(safe-area-inset-bottom, 0px));
  }

  html.lv-web .photo-card {
    min-height: 0;
  }

  /* Base rule hides the check until hover (styles.css :3015-3038); hover
     does not exist on touch, so force it on. !important beats the reveal
     chain in one declaration. */
  html.lv-web .photo-card .select-check {
    opacity: 1 !important;
    width: 26px;
    height: 26px;
  }

  /* Keep card chrome readable at ~110px-wide cards. */
  html.lv-web .photo-card .card-body {
    gap: 4px;
    padding: 6px 8px;
  }
  html.lv-web .photo-card .card-name {
    font-size: 11px;
  }
  html.lv-web .photo-card .badge {
    top: 5px;
    left: 5px;
    padding: 2px 5px;
    font-size: 8px;
  }

  /* --------------------------------------------------------------------------
     6. Bottom nav - Photos / Picks / Cull (accent circle) / Search / Menu.
        mobile-ui.js stamps html.lv-mnav only when nothing fullscreen is open.
     ------------------------------------------------------------------------ */
  html.lv-web #lvMobileNav {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1050;
    display: none;
    align-items: stretch;
    background: var(--panel);
    border-top: 1px solid var(--line);
    padding-bottom: env(safe-area-inset-bottom, 0px);
  }

  html.lv-web.lv-mnav #lvMobileNav {
    display: flex;
  }

  html.lv-web #lvMobileNav button {
    flex: 1 1 0;
    min-width: 0;
    height: 56px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    padding: 0;
    border: none;
    background: transparent;
    color: var(--muted);
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.01em;
    cursor: pointer;
  }

  html.lv-web #lvMobileNav button svg {
    width: 24px;
    height: 24px;
    display: block;
  }

  html.lv-web #lvMobileNav button.active {
    color: var(--accent);
  }

  /* Center Cull item: raised 44px accent circle around its icon. */
  html.lv-web #lvMobileNav .lv-nav-cull svg,
  html.lv-web #lvMobileNav [data-nav="cull"] svg {
    width: 44px;
    height: 44px;
    box-sizing: border-box;
    padding: 10px;
    margin-top: -18px;
    border-radius: 50%;
    background: var(--accent);
    color: var(--on-accent);
    box-shadow: 0 4px 14px color-mix(in srgb, var(--accent) 45%, transparent);
  }
  html.lv-web #lvMobileNav .lv-nav-cull,
  html.lv-web #lvMobileNav [data-nav="cull"] {
    overflow: visible;
  }

  /* Toast helper (mobile-ui.js) - sits just above the nav. */
  html.lv-web .lv-toast {
    position: fixed;
    left: 50%;
    bottom: calc(72px + env(safe-area-inset-bottom, 0px));
    transform: translateX(-50%);
    z-index: 2000;
    max-width: 92vw;
    padding: 10px 16px;
    border-radius: 12px;
    background: var(--panel);
    border: 1px solid var(--line);
    color: var(--text);
    font-size: 13px;
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.5);
  }

  /* --------------------------------------------------------------------------
     7. Empty state - a big tappable "Add photos" target (mobile-ui.js turns
        the whole zone into a picker button).
     ------------------------------------------------------------------------ */
  html.lv-web #dropZone {
    height: auto;
    flex: 1 1 auto;
    min-height: 0;
    margin: 24px 12px;
    padding: 40px 20px;
    border-radius: 16px;
    border: 1.5px dashed var(--line);
    text-align: center;
    cursor: pointer;
  }
  html.lv-web #dropZone:active {
    background: var(--raised);
  }
  html.lv-web #dropZone h3 {
    font-size: 22px;
  }

  /* --------------------------------------------------------------------------
     8. Cull overlay - the mobile hero. Swipe gestures come from mobile-ui.js;
        the classes below give the fly-off feedback. Desktop hover affordances
        (nav arrows, face gutters, keyboard hints) come off.
     ------------------------------------------------------------------------ */
  /* Solid backdrop: base is rgba+blur (styles.css :9905); blur is disabled on
     mobile for GPU cost, which would let the grid bleed through the alpha. */
  html.lv-web .cull-overlay {
    background: #05070a;
  }

  html.lv-web .cull-topbar {
    padding: 8px 10px;
    gap: 8px;
  }
  html.lv-web .cull-context {
    font-size: 12px;
    min-width: 0;
    white-space: nowrap;
  }

  /* The star dots and the "N left to review" tail overlap the position counter
     at 375px; the rating bar and queue select already carry both facts. */
  html.lv-web #cullRatingDots,
  html.lv-web #cullRemaining {
    display: none;
  }

  html.lv-web #cullQueueFilter {
    max-width: 132px;
    height: 40px;
    font-size: 13px;
  }

  /* Touch-size the topbar buttons (base 34px, styles.css :9958). */
  html.lv-web .cull-btn {
    width: 40px;
    height: 40px;
  }

  /* Edit button (mobile-ui.js injects before #cullExit). */
  html.lv-web #lvCullEdit {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    height: 40px;
    min-width: 40px;
    padding: 0 12px;
    border: 1px solid var(--line);
    border-radius: 8px;
    background: var(--raised);
    color: var(--text);
    font-size: 13px;
    font-weight: 700;
    cursor: pointer;
  }
  html.lv-web #lvCullEdit svg {
    width: 18px;
    height: 18px;
    display: block;
  }

  /* Keep the hint line: mobile-ui.js rewrites it with touch gestures. */
  html.lv-web .cull-hint {
    font-size: 11px;
    color: var(--muted);
    text-align: center;
    padding: 2px 8px 0;
  }
  html.lv-web #cullFacesLeft,
  html.lv-web #cullFacesRight {
    display: none !important;
  }
  html.lv-web .cull-nav {
    display: none;
  }

  /* Stage: full-bleed (the 64px face gutters are gone), gesture-owned. */
  html.lv-web #cullStage {
    padding: 6px 10px;
    touch-action: none;
    transition: transform 0.18s ease, opacity 0.18s ease;
  }

  /* Swipe fly-off feedback (mobile-ui.js adds/removes these). */
  html.lv-web #cullStage.lv-fly-left {
    transform: translateX(-18%) rotate(-2deg);
    opacity: 0.2;
  }
  html.lv-web #cullStage.lv-fly-right {
    transform: translateX(18%) rotate(2deg);
    opacity: 0.2;
  }
  html.lv-web #cullStage.lv-fly-up {
    transform: translateY(-24%) rotate(2deg);
    opacity: 0.15;
  }
  html.lv-web #cullStage.lv-fly-down {
    transform: translateY(18%) rotate(-2deg);
    opacity: 0.25;
  }

  /* Big touch rating bar. min-width: 0 undoes the 46px per-button floor so
     eight buttons can share a 375px row. */
  html.lv-web .cull-bottombar {
    align-self: stretch;
    padding: 10px 10px calc(10px + env(safe-area-inset-bottom, 0px));
    gap: 8px;
  }
  html.lv-web .cull-rating-bar {
    display: flex;
    width: 100%;
    gap: 8px;
  }
  html.lv-web .cull-rate-btn {
    flex: 1 1 0;
    min-width: 0;
    height: auto;
    min-height: 52px;
    font-size: 16px;
    padding: 0;
  }
  html.lv-web .cull-rate-btn.cull-act-pick,
  html.lv-web .cull-rate-btn.cull-act-reject {
    flex: 1.4 1 0;
    font-weight: 800;
  }
  html.lv-web .cull-rate-btn.cull-rate-clear {
    font-size: 12px;
  }

  html.lv-web .cull-toast {
    bottom: calc(96px + env(safe-area-inset-bottom, 0px));
    max-width: 92vw;
  }

  html.lv-web .cull-help-card {
    width: min(440px, 92vw);
    max-width: 92vw;
    max-height: 84dvh;
    overflow-y: auto;
  }

  /* Keyboard shortcut table is meaningless on touch; mobile-ui.js swaps the
     card's intro paragraph for the swipe story. */
  html.lv-web .cull-help-keys {
    display: none;
  }

  /* --------------------------------------------------------------------------
     9. Editor - image on top, develop panel as a draggable bottom sheet.
        Note: .inspector:has(#developPanel:not([hidden])) (styles.css :6535)
        carries id-level specificity and keeps display:flex/padding:0 while
        the panel is visible - exactly what the sheet wants; the properties
        below don't collide with it.
     ------------------------------------------------------------------------ */
  html.lv-web .app-shell.editor-open aside.inspector {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    top: auto;
    height: var(--lv-sheet-h, 46dvh);
    z-index: 1000;
    border-radius: 16px 16px 0 0;
    border-top: 1px solid var(--line);
    border-left: none;
    box-shadow: 0 -12px 40px rgba(0, 0, 0, 0.45);
    transition: height 0.22s ease;
    overflow: hidden;
    display: block;
  }
  /* Explicit tall stop — MUST track the --lv-sheet-h token block above; a
     literal height here outranks the var and silently pins the old value. */
  html.lv-web.lv-sheet-tall .app-shell.editor-open aside.inspector {
    height: var(--lv-sheet-h, 72dvh);
  }

  /* Outside the editor there is no inspector column on a phone. !important
     out-ranks the :has() rule above should the develop panel ever be left
     unhidden while the editor is closed. */
  html.lv-web .app-shell:not(.editor-open) aside.inspector {
    display: none !important;
  }

  html.lv-web .app-shell.editor-open .develop-panel {
    height: 100%;
    min-height: 0;
  }

  /* Drag pill (mobile-ui.js keeps it as the inspector's first child). */
  html.lv-web #lvSheetHandle {
    display: flex;
    justify-content: center;
    padding: 8px 0 2px;
    flex: 0 0 auto;
    touch-action: none;
    cursor: grab;
  }
  html.lv-web #lvSheetHandle::before {
    content: "";
    width: 36px;
    height: 4px;
    border-radius: 2px;
    background: var(--muted);
  }

  html.lv-web .app-shell.editor-open .develop-scroll {
    padding-bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  }

  /* Stage + filmstrip + footer sit above the sheet. */
  html.lv-web .app-shell.editor-open .editor-view {
    inset: 0 0 var(--lv-sheet-h, 46dvh) 0;
    transition: bottom 0.22s ease;
  }

  /* Slim the sticky head: on a phone every saved pixel is slider room. The
     histogram stays useful at 56px; header and tabs tighten. */
  html.lv-web .develop-sticky .develop-header {
    padding: 4px 12px 2px;
  }
  html.lv-web #developHistogram {
    height: 56px;
  }
  html.lv-web .develop-scopes {
    margin: 4px 12px;
  }

  /* Tab bar: the 5-column grid (styles.css :6582) becomes a horizontal
     scroller with 44px touch targets. */
  html.lv-web .develop-tabs {
    display: flex;
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    gap: 4px;
  }
  html.lv-web .develop-tabs::-webkit-scrollbar {
    display: none;
  }

  /* Double-tap on Android zooms any surface that allows it — inside the app
     chrome that fights slider double-tap-reset and reads as jank. manipulation
     keeps scrolling and pinch but kills the double-tap zoom gesture. */
  html.lv-web #developPanel,
  html.lv-web #developPanel * ,
  html.lv-web .editor-footer,
  html.lv-web .editor-footer * ,
  html.lv-web #lvMobileNav,
  html.lv-web .cull-bottombar,
  html.lv-web .cull-bottombar * ,
  html.lv-web .cull-topbar,
  html.lv-web .editor-filmstrip {
    touch-action: manipulation;
  }

  /* Footer diet: Crop lives in its tab, aspect + auto-crop live in the crop
     strip chips, and the format choice moved into the Export sheet. The row
     shrinks to Back to grid - Loupe - Export. */
  html.lv-web .editor-footer-actions #cropToggle,
  html.lv-web .editor-footer-actions #cropAspect,
  html.lv-web .editor-footer-actions #cropAuto,
  html.lv-web .editor-footer-actions #editorFormat {
    display: none !important;
  }

  /* AI Generate and Sky Replacement run on the server-side engine the web
     build can't reach yet — dead accent buttons are worse than absence. The
     in-browser features (FaceRestore, AI Restore, Fix Eyes, Portrait,
     Expression) are the tab. */
  html.lv-web .develop-tabpanel[data-panel="ai"] .develop-generate,
  html.lv-web .develop-tabpanel[data-panel="ai"] #skySection {
    display: none;
  }

  /* --------------------------------------------------------------------------
     Scrub mode - photo-first Adjust (Samsung-Gallery-style). The sheet shrinks
     to handle + label/value + pill row + ruler + tab row; the photo gets the
     rest. mobile-ui.js owns entering/leaving (html.lv-scrub) and the pills.
     ------------------------------------------------------------------------ */
  html.lv-web.lv-scrub {
    --lv-sheet-h: calc(212px + env(safe-area-inset-bottom, 0px));
  }
  /* Tabs with a context-chip row (crop aspects, add-mask, lights, remove modes)
     need one more row of sheet. */
  html.lv-web.lv-scrub.lv-has-chips {
    --lv-sheet-h: calc(258px + env(safe-area-inset-bottom, 0px));
  }
  html.lv-web.lv-scrub .app-shell.editor-open aside.inspector {
    display: flex;
    flex-direction: column;
  }
  html.lv-web.lv-scrub .develop-sticky {
    padding: 0;
    margin: 0;
  }
  html.lv-web.lv-scrub .develop-sticky > :not(.develop-tabs) {
    display: none !important;
  }
  html.lv-web.lv-scrub .develop-scroll {
    display: none !important;
  }
  html.lv-web.lv-scrub .app-shell.editor-open .develop-panel {
    height: auto;
    margin-top: auto;
  }
  html.lv-web.lv-scrub .develop-tabs {
    padding-bottom: calc(4px + env(safe-area-inset-bottom, 0px));
  }
  /* Full-bleed photo: the filmstrip yields; stage swipes navigate instead. */
  html.lv-web.lv-scrub .app-shell.editor-open .editor-filmstrip {
    display: none;
  }

  html.lv-web #lvScrubBar {
    display: none;
  }
  html.lv-web.lv-scrub #lvScrubBar {
    display: block;
  }
  /* Context chips: proxies for the tab's real controls (aspect ratios, add
     mask, quick lights, remove modes). Accent = the tab's primary action. */
  html.lv-web .lv-scrub-chips {
    display: flex;
    flex-wrap: nowrap;
    gap: 6px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding: 6px 12px 2px;
  }
  html.lv-web .lv-scrub-chips::-webkit-scrollbar {
    display: none;
  }
  html.lv-web .lv-scrub-chip {
    flex: 0 0 auto;
    min-height: 34px;
    padding: 0 12px;
    border-radius: 17px;
    background: var(--field);
    border: 1px solid var(--line);
    color: var(--muted);
    font-size: 12px;
    touch-action: manipulation;
  }
  html.lv-web .lv-scrub-chip.active {
    color: var(--accent);
    border-color: var(--accent);
    background: var(--raised);
  }
  html.lv-web .lv-scrub-chip.lv-accent {
    color: var(--on-accent);
    background: var(--accent);
    border-color: var(--accent);
  }

  html.lv-web .lv-scrub-hint {
    font-size: 12px;
    color: var(--muted);
    text-align: center;
    padding: 14px 24px;
    line-height: 1.5;
  }
  /* No pills to scrub (no mask/light selected yet): hide the ruler chrome. */
  html.lv-web #lvScrubBar.lv-strip-empty .lv-scrub-top,
  html.lv-web #lvScrubBar.lv-strip-empty .lv-scrub-pills,
  html.lv-web #lvScrubBar.lv-strip-empty #lvScrubRuler {
    display: none;
  }

  html.lv-web .lv-scrub-top {
    display: flex;
    justify-content: center;
    align-items: baseline;
    gap: 8px;
    min-height: 18px;
    font-size: 12px;
    color: var(--muted);
  }
  html.lv-web #lvScrubVal {
    color: var(--text);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
  }
  html.lv-web .lv-scrub-pills {
    display: flex;
    flex-wrap: nowrap;
    gap: 8px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding: 8px 12px 6px;
  }
  html.lv-web .lv-scrub-pills::-webkit-scrollbar {
    display: none;
  }
  html.lv-web .lv-scrub-pill {
    flex: 0 0 auto;
    min-height: 38px;
    padding: 0 14px;
    border-radius: 19px;
    background: var(--field);
    border: 1px solid var(--line);
    color: var(--muted);
    font-size: 13px;
    position: relative;
    touch-action: manipulation;
  }
  html.lv-web .lv-scrub-pill.active {
    color: var(--accent);
    border-color: var(--accent);
    background: var(--raised);
  }
  /* Edited-away-from-default dot, mirroring pro-app convention. */
  html.lv-web .lv-scrub-pill.lv-mod::after {
    content: "";
    position: absolute;
    bottom: 4px;
    left: 50%;
    transform: translateX(-50%);
    width: 4px;
    height: 4px;
    border-radius: 50%;
    background: var(--accent);
  }
  html.lv-web #lvScrubRuler {
    position: relative;
    height: 54px;
    touch-action: none;
    cursor: ew-resize;
  }
  html.lv-web .lv-scrub-ticks {
    position: absolute;
    inset: 10px 0;
    background-image: repeating-linear-gradient(90deg, var(--muted) 0 1px, transparent 1px 9px);
    background-position: 50% 0;
    opacity: 0.5;
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 18%, #000 82%, transparent);
    mask-image: linear-gradient(90deg, transparent, #000 18%, #000 82%, transparent);
  }
  html.lv-web .lv-scrub-center {
    position: absolute;
    top: 4px;
    bottom: 4px;
    left: 50%;
    width: 2px;
    margin-left: -1px;
    background: var(--accent);
    border-radius: 1px;
  }

  /* Crop rect: finger-sized targets. Visible handles grow (base 14px corners /
     26x8 edges, styles.css :6122-6150 — offsets re-centered to match), and an
     invisible ::after pad grows the hit area further without moving anything. */
  html.lv-web .crop-h {
    width: 22px;
    height: 22px;
  }
  html.lv-web .crop-h.tl { left: -11px; top: -11px; }
  html.lv-web .crop-h.tr { right: -11px; top: -11px; }
  html.lv-web .crop-h.bl { left: -11px; bottom: -11px; }
  html.lv-web .crop-h.br { right: -11px; bottom: -11px; }
  html.lv-web .crop-e.t { width: 34px; height: 14px; top: -7px; margin-left: -17px; }
  html.lv-web .crop-e.b { width: 34px; height: 14px; bottom: -7px; margin-left: -17px; }
  html.lv-web .crop-e.l { width: 14px; height: 34px; left: -7px; margin-top: -17px; }
  html.lv-web .crop-e.r { width: 14px; height: 34px; right: -7px; margin-top: -17px; }
  html.lv-web .crop-h::after,
  html.lv-web .crop-e::after {
    content: "";
    position: absolute;
    inset: -12px;
  }

  /* AI tab keeps the half sheet — just make its cards and buttons thumb-sized. */
  html.lv-web .develop-tabpanel[data-panel="ai"] .tool-btn {
    min-height: 44px;
  }
  html.lv-web .develop-tabpanel[data-panel="ai"] input[type="range"] {
    min-height: 30px;
  }

  /* --------------------------------------------------------------------------
     Client gallery studio - phone-first. Desktop nests three layers of padding
     (browser 26px + studio 32px + 16px margin) that squeezed the builder to
     224px; on a phone the studio goes full-bleed, tabs become a real segmented
     bar, option tiles get a 2-up touch grid, and the live preview stretches.
     ------------------------------------------------------------------------ */
  html.lv-web #clientGalleryBrowser {
    padding: 10px 10px calc(76px + env(safe-area-inset-bottom, 0px));
  }
  html.lv-web .client-gallery-studio {
    margin: 0;
    padding: 12px 10px 16px;
    border-radius: 14px;
  }
  html.lv-web #cgInlineBuilder.cg-inline {
    grid-template-columns: 1fr;
    gap: 14px;
  }

  /* Gallery rail: horizontal chip scroller + a clear New-gallery action. */
  html.lv-web .cg-gallery-rail {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
  }
  html.lv-web .cg-rail-left {
    width: 100%;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
  }
  html.lv-web .cg-rail-chips {
    flex: 1 1 100%;
    display: flex;
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    gap: 8px;
    order: 2;
  }
  html.lv-web .cg-rail-chips::-webkit-scrollbar {
    display: none;
  }
  html.lv-web .cg-rail-chip {
    flex: 0 0 auto;
    min-height: 48px;
  }
  html.lv-web .cg-add {
    order: 1;
    margin-left: auto;
  }
  html.lv-web .cg-add-chip {
    min-height: 40px;
  }
  /* The New-gallery source popover anchored off-screen right at 384px. */
  html.lv-web .cg-add-menu {
    left: auto;
    right: 0;
    max-width: calc(100vw - 32px);
  }

  /* Side tabs: full-width 4-up segmented bar. */
  html.lv-web .cg-sidebar-tabs {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 4px;
    width: 100%;
    padding: 4px;
    border: 1px solid var(--line);
    border-radius: 12px;
    background: var(--field);
  }
  html.lv-web .cg-side-tab {
    width: auto;
    min-height: 56px;
    border-radius: 9px;
  }
  html.lv-web .cg-side-tab.active {
    background: var(--raised);
    color: var(--accent);
  }

  /* Design sub-tabs (Cover / Type / Color / Grid): thumb chips. */
  html.lv-web .cg-design-pills {
    display: flex;
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    gap: 8px;
    padding: 2px 0 8px;
  }
  html.lv-web .cg-design-pills::-webkit-scrollbar {
    display: none;
  }
  html.lv-web .cg-design-pills button {
    flex: 0 0 auto;
    min-height: 40px;
    padding: 0 16px;
    border-radius: 20px;
  }

  /* One page scroll, not a scroll-within-a-card: the controls body loses its
     desktop height cap and grows naturally. */
  html.lv-web .cg-sidebar {
    height: auto;
  }
  html.lv-web .cg-sidebar-body {
    max-height: none !important;
    overflow: visible;
  }

  /* Option sections become cards; tile pickers a proper 2-up touch grid. */
  html.lv-web .client-options-panel {
    width: 100%;
  }
  /* Sections live INSIDE the light-remapped builder card — no dark repaint
     (their labels are dark-on-light by design); spacing only. */
  html.lv-web .client-option-section {
    width: 100%;
    padding: 0;
    margin-bottom: 16px;
  }
  html.lv-web .client-option-section-head {
    width: 100%;
    margin-bottom: 10px;
  }
  html.lv-web .client-option-section-head strong {
    font-size: 12px;
    letter-spacing: 0.08em;
    color: var(--muted);
  }
  html.lv-web .client-option-grid {
    width: 100%;
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
  }
  html.lv-web .client-option-card {
    width: 100%;
    min-height: 104px;
    border-radius: 12px;
  }

  /* Live preview: full width, generous height, touch-size device toggles. */
  html.lv-web .cg-preview-pane {
    width: 100%;
  }
  html.lv-web .cg-preview-toolbar {
    min-height: 48px;
  }
  html.lv-web .cg-preview-toolbar .wpv-dev {
    min-width: 44px;
    min-height: 40px;
  }
  html.lv-web .client-fullscreen-stage {
    width: 100%;
    height: 62dvh;
    min-height: 380px;
  }

  /* Action buttons: full-width, stacked, thumbable. */
  html.lv-web .cg-sidebar-actions {
    display: flex;
    flex-direction: column;
    gap: 8px;
  }
  html.lv-web .cg-sidebar-actions button {
    width: 100%;
    min-height: 46px;
  }

  /* --------------------------------------------------------------------------
     RADICAL gallery builder (html.lv-cg-open) - mirrors the develop editor: the
     client's live gallery preview fills the screen full-bleed; the design
     controls become a bottom sheet over it. mobile-ui.js stamps lv-cg-open only
     while the inline builder is open on a phone, and measures the header into
     --lv-cg-top. Every rule is scoped under #clientGalleryBrowser so the website
     builder and desktop editor (which share the .wpv-* frame) are untouched.
     ------------------------------------------------------------------------ */
  html.lv-cg-open {
    --cg-sheet-h: 46dvh;
  }
  html.lv-cg-open.lv-cg-tall {
    --cg-sheet-h: 84dvh;
  }

  /* Full-screen takeover between the app header and the bottom nav. */
  html.lv-cg-open #clientGalleryBrowser {
    position: fixed;
    left: 0;
    right: 0;
    top: var(--lv-cg-top, 52px);
    bottom: calc(56px + env(safe-area-inset-bottom, 0px));
    z-index: 30;
    padding: 0;
    overflow: hidden;
  }
  html.lv-cg-open #clientGalleryBrowser .client-gallery-studio {
    margin: 0;
    padding: 0;
    border-radius: 0;
    height: 100%;
    display: flex;
    flex-direction: column;
    background: var(--bg);
  }

  /* Gallery switcher = slim single-row strip (the big list chips are for the
     gallery LIST; in the builder it's just a compact switcher). */
  html.lv-cg-open #clientGalleryBrowser .cg-gallery-rail {
    flex: 0 0 auto;
    padding: 6px 8px;
    border-bottom: 1px solid var(--line);
  }
  html.lv-cg-open #clientGalleryBrowser .cg-rail-left {
    flex-wrap: nowrap;
  }
  html.lv-cg-open #clientGalleryBrowser .cg-gallery-rail .eyebrow {
    display: none;
  }
  html.lv-cg-open #clientGalleryBrowser .cg-rail-chips {
    order: 0;
    flex: 1 1 auto;
  }
  html.lv-cg-open #clientGalleryBrowser .cg-rail-chip {
    min-height: 40px;
    padding: 3px 10px 3px 3px;
  }
  html.lv-cg-open #clientGalleryBrowser .cg-rail-chip .cg-chip-thumb {
    width: 30px;
    height: 30px;
  }
  html.lv-cg-open #clientGalleryBrowser .cg-add {
    order: 1;
    margin: 0 0 0 6px;
  }
  html.lv-cg-open #clientGalleryBrowser .cg-add-chip {
    min-height: 40px;
    padding: 0 12px;
    white-space: nowrap;
  }
  /* Sheet already names the gallery via the active rail chip. */
  html.lv-cg-open #clientGalleryBrowser .cg-sidebar-id {
    display: none;
  }

  /* Builder fills; preview + sheet are its positioned children. */
  html.lv-cg-open #clientGalleryBrowser #cgInlineBuilder.cg-inline {
    display: block;
    position: relative;
    flex: 1 1 auto;
    min-height: 0;
    gap: 0;
    margin: 0;
  }

  /* PREVIEW: full-bleed, above the sheet. The device frame/bezel is stripped and
     the scale transform neutralized so the responsive preview page renders at the
     real screen width instead of a scaled 390px fake phone. */
  html.lv-cg-open #clientGalleryBrowser .cg-preview-pane {
    position: absolute;
    inset: 0 0 var(--cg-sheet-h, 46dvh) 0;
    width: auto;
    transition: bottom 0.22s ease;
  }
  html.lv-cg-open #clientGalleryBrowser .cg-preview-toolbar {
    display: none;
  }
  html.lv-cg-open #clientGalleryBrowser .client-fullscreen-stage {
    position: absolute;
    inset: 0;
    height: auto;
    min-height: 0;
    padding: 0;
    background: var(--bg);
    overflow: hidden;
  }
  html.lv-cg-open #clientGalleryBrowser .cg-device-wrap,
  html.lv-cg-open #clientGalleryBrowser .cg-wpv-stage {
    display: block;
    width: 100%;
    height: 100%;
    min-height: 0;
  }
  html.lv-cg-open #clientGalleryBrowser .wpv-stage {
    padding: 0;
    background: none;
    min-height: 0;
    display: block;
  }
  html.lv-cg-open #clientGalleryBrowser .wpv-frame {
    padding: 0 !important;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    background: var(--bg);
    display: block;
    width: 100%;
    height: 100%;
  }
  html.lv-cg-open #clientGalleryBrowser .wpv-chrome,
  html.lv-cg-open #clientGalleryBrowser .wpv-notch {
    display: none !important;
  }
  html.lv-cg-open #clientGalleryBrowser .wpv-screen {
    border-radius: 0;
    width: 100%;
    height: 100%;
  }
  html.lv-cg-open #clientGalleryBrowser .wpv-scaler {
    transform: none !important;
    width: 100% !important;
    height: 100% !important;
  }
  html.lv-cg-open #clientGalleryBrowser .wpv-iframe {
    transform: none !important;
    width: 100% !important;
    height: 100% !important;
  }

  /* CONTROLS: bottom sheet over the preview. */
  html.lv-cg-open #clientGalleryBrowser .cg-sidebar {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: var(--cg-sheet-h, 46dvh);
    z-index: 2;
    background: var(--panel);
    border-top: 1px solid var(--line);
    border-radius: 16px 16px 0 0;
    box-shadow: 0 -12px 40px rgba(0, 0, 0, 0.4);
    display: flex;
    flex-direction: column;
    transition: height 0.22s ease;
    overflow: hidden;
    padding: 0;
  }
  /* Drag handle (injected). */
  html.lv-cg-open #clientGalleryBrowser #lvCgHandle {
    flex: 0 0 auto;
    display: flex;
    justify-content: center;
    padding: 8px 0 4px;
    cursor: grab;
    touch-action: none;
  }
  html.lv-cg-open #clientGalleryBrowser #lvCgHandle::before {
    content: "";
    width: 36px;
    height: 4px;
    border-radius: 2px;
    background: var(--muted);
  }
  html.lv-cg-open #clientGalleryBrowser .cg-sidebar-id {
    flex: 0 0 auto;
    padding: 0 12px 6px;
  }
  /* Slim the top tabs to a label-only segmented bar (icons stacked over labels
     ate ~56px; labels alone are ~38px, reclaiming vertical space). */
  html.lv-cg-open #clientGalleryBrowser .cg-sidebar-tabs {
    flex: 0 0 auto;
    margin: 0 10px 6px;
    padding: 3px;
    grid-auto-rows: 38px;
  }
  html.lv-cg-open #clientGalleryBrowser .cg-side-tab {
    min-height: 0 !important;
    height: 38px !important;
    flex-direction: row;
    gap: 0;
    font-size: 12px;
    padding: 0 4px;
  }
  html.lv-cg-open #clientGalleryBrowser .cg-side-tab-ic {
    display: none;
  }
  html.lv-cg-open #clientGalleryBrowser .cg-sidebar-body {
    flex: 1 1 auto;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    max-height: none !important;
    padding: 0 10px 10px;
  }
  /* The builder controls are always light (they edit a light client page); on
     the dark sheet, contain them as one deliberate light canvas card rather
     than a full-bleed white bleed. */
  html.lv-cg-open #clientGalleryBrowser .client-options-panel {
    background: #fff;
    border-radius: 12px;
    padding: 10px;
    margin-top: 2px;
  }

  /* Compact every option area for the phone sheet — the desktop tiles are
     ~141px tall; shrink the previews + tighten spacing so several rows fit
     without endless scrolling. Applies across Cover/Type/Color/Grid and the
     Sharing/Sell/Advanced controls. */
  html.lv-cg-open #clientGalleryBrowser .client-option-section {
    margin-bottom: 10px;
  }
  html.lv-cg-open #clientGalleryBrowser .client-option-section-head {
    margin-bottom: 6px;
  }
  html.lv-cg-open #clientGalleryBrowser .client-option-section-head strong {
    font-size: 11px;
    letter-spacing: 0.06em;
  }
  html.lv-cg-open #clientGalleryBrowser .client-option-grid {
    gap: 8px;
  }
  html.lv-cg-open #clientGalleryBrowser .client-option-card {
    min-height: 0 !important;
    border-radius: 10px;
    gap: 4px;
  }
  /* The preview thumb is the tall part (116px on desktop) — cap it. */
  html.lv-cg-open #clientGalleryBrowser .client-option-thumb {
    height: 62px !important;
    min-height: 0 !important;
    overflow: hidden;
  }
  /* The card's text label under the thumb. */
  html.lv-cg-open #clientGalleryBrowser .client-option-card > span:last-child {
    font-size: 12px;
    padding-bottom: 6px;
  }
  /* Cover: shrink the hero preview image. */
  html.lv-cg-open #clientGalleryBrowser .client-cover-card-hero,
  html.lv-cg-open #clientGalleryBrowser .client-cover-card-hero img {
    height: 62px !important;
    object-fit: cover;
  }
  html.lv-cg-open #clientGalleryBrowser .client-cover-card-title b {
    font-size: 12px;
  }
  html.lv-cg-open #clientGalleryBrowser .client-cover-card-title span {
    font-size: 9px;
  }
  /* Type: shrink the font-sample preview. */
  html.lv-cg-open #clientGalleryBrowser .typography-option-thumb strong {
    font-size: 18px;
  }
  html.lv-cg-open #clientGalleryBrowser .typography-option-thumb small {
    font-size: 10px;
  }
  /* Color: shrink the swatch row. */
  html.lv-cg-open #clientGalleryBrowser .client-color-swatch-row {
    height: 40px;
  }

  /* Sharing / Sell / Advanced: compact rows, toggles, selects, inputs. */
  html.lv-cg-open #clientGalleryBrowser .cg-sidebar-body label {
    font-size: 13px;
  }
  html.lv-cg-open #clientGalleryBrowser .cg-sidebar-body select,
  html.lv-cg-open #clientGalleryBrowser .cg-sidebar-body input[type="text"],
  html.lv-cg-open #clientGalleryBrowser .cg-sidebar-body input[type="number"],
  html.lv-cg-open #clientGalleryBrowser .cg-sidebar-body input[type="url"] {
    height: 40px !important;
    min-height: 0 !important;
    font-size: 15px;
    padding: 0 12px !important;
  }
  /* Tighten the form field vertical rhythm (label + input stacks). */
  html.lv-cg-open #clientGalleryBrowser .cover-brand-field {
    margin-top: 6px !important;
  }
  html.lv-cg-open #clientGalleryBrowser .cover-brand-field > span:first-child,
  html.lv-cg-open #clientGalleryBrowser .cover-brand-field label {
    margin-bottom: 4px;
  }
  /* Choose-file / secondary buttons in the forms. */
  html.lv-cg-open #clientGalleryBrowser .cg-sidebar-body .tool-btn:not(.cg-act) {
    min-height: 40px;
  }
  /* Compact action bar: ONE row — Arrange · Open (content-width secondaries)
     and Publish filling the rest. The desktop CTAs balloon to 73-154px via
     flex-grow in a column, so cap hard + single row (~42px total). */
  html.lv-cg-open #clientGalleryBrowser .cg-sidebar-actions {
    flex: 0 0 auto;
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    align-items: stretch;
    gap: 6px;
    border-top: 1px solid var(--line);
    padding: 8px 10px calc(8px + env(safe-area-inset-bottom, 0px));
    background: var(--panel);
    margin: 0;
  }
  html.lv-cg-open #clientGalleryBrowser .cg-sidebar-actions button {
    flex: 0 1 auto;
    width: auto;
    min-height: 0 !important;
    height: 42px !important;
    max-height: 42px;
    padding: 0 12px !important;
    font-size: 13px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  /* Publish (the primary) fills the remaining width. */
  html.lv-cg-open #clientGalleryBrowser .cg-sidebar-actions button.accent {
    flex: 1 1 auto;
    order: 3;
    min-width: 0;
  }
  html.lv-web .develop-tab {
    flex: 0 0 auto;
    min-height: 44px;
    padding: 0 14px;
    justify-content: center;
  }

  /* Footer: compact, wrappable, touch-size buttons. */
  html.lv-web .editor-footer {
    flex-wrap: nowrap;
    gap: 0;
    padding: 6px 0;
  }
  html.lv-web .editor-footer .editor-zoom-hint {
    display: none;
  }
  /* The filename lives in the sheet header; free the row for controls. */
  html.lv-web .editor-footer .editor-name {
    display: none;
  }
  /* One thumb-scrollable row, but Back and Export stay pinned at the edges —
     they are the two actions a phone user must never have to hunt for. */
  html.lv-web .editor-footer-actions {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    gap: 8px;
    overflow-x: auto;
    scrollbar-width: none;
    padding: 0 10px;
  }
  html.lv-web .editor-footer-actions::-webkit-scrollbar {
    display: none;
  }
  html.lv-web .editor-footer-actions > * {
    flex: 0 0 auto;
  }
  html.lv-web .editor-footer-actions #editorClose {
    order: -1;
    position: sticky;
    left: 0;
    z-index: 2;
    background: var(--raised);
  }
  html.lv-web .editor-footer-actions #editorExport {
    position: sticky;
    right: 0;
    z-index: 2;
  }
  html.lv-web .editor-footer button {
    height: auto;
    min-height: 40px;
  }

  /* Filmstrip: bigger touch targets (~76px tall strip, 100x68 items). */
  html.lv-web .editor-filmstrip {
    padding: 4px 10px;
  }
  html.lv-web .filmstrip-item {
    width: 100px;
    height: 68px;
  }

  /* --------------------------------------------------------------------------
     10. Modals become bottom sheets; menus and popovers fit the viewport.
     ------------------------------------------------------------------------ */
  html.lv-web .modal-overlay {
    align-items: flex-end;
    padding: 0;
  }

  html.lv-web .modal-card,
  html.lv-web .settings-card,
  html.lv-web .people-coverage-card,
  html.lv-web .people-hub-card,
  html.lv-web .shotlist-editor-card,
  html.lv-web .checklist-send-card,
  html.lv-web .setup-wizard {
    width: 100%;
    max-width: 100% !important;
    border-radius: 16px 16px 0 0;
    max-height: 88dvh;
    overflow-y: auto;
  }

  /* Settings card internals: single column (base is a 2-col grid). */
  html.lv-web .settings-live-controls {
    grid-template-columns: 1fr;
  }

  html.lv-web .context-menu {
    min-width: 220px;
    max-width: 92vw;
  }
  html.lv-web .context-menu-item {
    min-height: 44px;
    padding: 10px 12px;
  }
  html.lv-web .context-submenu {
    max-width: 80vw;
  }

  html.lv-web .search-options-pop,
  html.lv-web .bg-loader-popover {
    max-width: 92vw;
  }

  html.lv-web .hub-overlay {
    grid-template-columns: 1fr;
  }
  html.lv-web .hub-card {
    width: auto;
    max-width: 94vw;
  }

  html.lv-web .tour-card,
  html.lv-web .tour-welcome-card,
  html.lv-web .onboard-card,
  html.lv-web .onboard-explainer-panel {
    max-width: 92vw;
  }

  /* Mobile menu / search sheets (created by mobile-ui.js, z 1600 over their
     own scrims at 1590). */
  html.lv-web .lv-sheet-scrim {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.5);
    z-index: 1590;
  }

  html.lv-web #lvMenuSheet,
  html.lv-web #lvSearchSheet,
  html.lv-web #lvExportSheet {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1600;
    background: var(--panel);
    border-top: 1px solid var(--line);
    border-radius: 16px 16px 0 0;
    box-shadow: 0 -12px 40px rgba(0, 0, 0, 0.45);
    padding: 12px 14px calc(14px + env(safe-area-inset-bottom, 0px));
    max-height: 76dvh;
    overflow-y: auto;
  }

  html.lv-web #lvMenuSheet {
    display: flex;
    flex-direction: column;
    gap: 2px;
  }
  html.lv-web #lvMenuSheet button {
    display: flex;
    align-items: center;
    gap: 12px;
    min-height: 44px;
    padding: 0 8px;
    border: none;
    border-radius: 10px;
    background: transparent;
    color: var(--text);
    font-size: 14px;
    font-weight: 600;
    text-align: left;
    cursor: pointer;
  }
  html.lv-web #lvMenuSheet button:active {
    background: var(--raised);
  }
  html.lv-web #lvMenuSheet button svg {
    width: 22px;
    height: 22px;
    flex: 0 0 auto;
    color: var(--muted);
  }
  /* Muted footer line ("Galleries, website & bookings live in the desktop app."). */
  html.lv-web #lvMenuSheet .lv-sheet-note,
  html.lv-web #lvMenuSheet p {
    margin: 8px 8px 0;
    color: var(--muted);
    font-size: 12px;
    line-height: 1.45;
  }

  /* Export sheet: pick a format, then one accent action. */
  html.lv-web .lv-export-title {
    font-size: 15px;
    font-weight: 700;
    color: var(--text);
    margin: 2px 4px 10px;
  }
  html.lv-web .lv-export-row {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    width: 100%;
    min-height: 52px;
    padding: 8px 12px;
    margin-bottom: 6px;
    border: 1px solid var(--line);
    border-radius: 12px;
    background: var(--field);
    color: var(--text);
    font-size: 14px;
    font-weight: 600;
    text-align: left;
    cursor: pointer;
    touch-action: manipulation;
  }
  html.lv-web .lv-export-row small {
    color: var(--muted);
    font-size: 12px;
    font-weight: 400;
  }
  html.lv-web .lv-export-row.active {
    border-color: var(--accent);
    color: var(--accent);
  }
  html.lv-web .lv-export-row.active small {
    color: var(--accent);
    opacity: 0.75;
  }
  html.lv-web .lv-export-go {
    width: 100%;
    min-height: 48px;
    margin-top: 4px;
    border: none;
    border-radius: 12px;
    background: var(--accent);
    color: var(--on-accent);
    font-size: 15px;
    font-weight: 700;
    cursor: pointer;
    touch-action: manipulation;
  }

  html.lv-web #lvSearchSheet,
  html.lv-web #lvSearchSheet form {
    display: flex;
    gap: 8px;
    align-items: center;
  }
  html.lv-web #lvSearchSheet form {
    flex: 1 1 auto;
    min-width: 0;
  }
  html.lv-web #lvSearchSheet input {
    flex: 1 1 auto;
    min-width: 0;
    min-height: 44px;
    padding: 0 12px;
    border: 1px solid var(--line);
    border-radius: 10px;
    background: var(--field);
    color: var(--text);
  }
  html.lv-web #lvSearchSheet button {
    flex: 0 0 auto;
    min-height: 44px;
    padding: 0 16px;
    border: none;
    border-radius: 10px;
    background: var(--accent);
    color: var(--on-accent);
    font-weight: 700;
    cursor: pointer;
  }

  /* --------------------------------------------------------------------------
     11. Hover reveals forced visible - hover does not exist on touch.
     ------------------------------------------------------------------------ */
  html.lv-web .folder-del,
  html.lv-web .folder-slideshow {
    opacity: 1;
  }
  html.lv-web .saved-look-delete {
    display: flex;
  }
  html.lv-web .gallery-item-del,
  html.lv-web .wp-remove {
    opacity: 1;
  }
  html.lv-web .pf-tile-check {
    opacity: 1;
  }

  /* --------------------------------------------------------------------------
     12. Touch hygiene - 16px inputs stop iOS focus-zoom, bigger slider thumbs,
        no 300ms double-tap zoom on buttons, and no expensive backdrop blurs
        on mobile GPUs.
     ------------------------------------------------------------------------ */
  html.lv-web input[type="text"],
  html.lv-web input[type="search"],
  html.lv-web input[type="email"],
  html.lv-web input[type="password"],
  html.lv-web input[type="number"],
  html.lv-web input[type="url"],
  html.lv-web select,
  html.lv-web textarea {
    font-size: 16px;
  }

  html.lv-web button {
    touch-action: manipulation;
  }

  html.lv-web .tool-btn {
    height: auto;
    min-height: 40px;
  }

  /* Range sliders: a 28px input band with an enlarged thumb keeps every
     develop slider finger-draggable. Base thumb is 16x14 over a 3px track
     (styles.css :7845); margin-top re-centres the bigger one. */
  html.lv-web input[type="range"] {
    min-height: 24px;
  }
  html.lv-web .develop-panel input[type="range"] {
    height: 28px;
  }
  html.lv-web .develop-panel input[type="range"]::-webkit-slider-thumb {
    width: 22px;
    height: 20px;
    margin-top: -8.5px;
  }

  html.lv-web .crop-extend-bar,
  html.lv-web .cull-overlay,
  html.lv-web .cull-hud-chip,
  html.lv-web .loupe-overlay {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }

  /* --------------------------------------------------------------------------
     13. Loupe / compare overlays - touch-size controls, full-bleed image.
     ------------------------------------------------------------------------ */
  html.lv-web .loupe-overlay img {
    max-width: 100vw;
  }
  html.lv-web .loupe-stage {
    padding: 8px;
  }
  html.lv-web .loupe-toolbar {
    padding: 8px 10px;
  }
  html.lv-web .loupe-toolbar button,
  html.lv-web .compare-overlay button {
    min-width: 44px;
    min-height: 44px;
  }
  html.lv-web .loupe-hint {
    display: none;
  }
}
