    *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

    /* NOTE: the portrait-only lock for phones lives at the very BOTTOM of this
       file. It used to sit here, which is exactly why it never worked: its
       `body`/`.phone-shell` sizing has the same specificity as the plain
       `html, body { width:100%; height:100% }` and `.phone-shell { width:100vw }`
       rules below, so those later rules won every time and the rotated box kept
       the phone's physical landscape dimensions. Do not move it back up. */

    :root {
      /* ── Shipdexa brand palette ── */
      --navy:        #17324D;   /* Dock Navy   — primary, headers, nav */
      --harbor:      #2E648A;   /* Harbor Blue — secondary nav, hover  */
      --teal:        #0F8A83;   /* Route Teal  — action, active, CTA   */
      --teal-dark:   #0A6B65;
      --teal-mid:    #0F8A83;
      --teal-light:  #DDF4F1;   /* Aqua Mist   — selected, light bg   */
      --teal-pale:   #EEF9F8;
      --accent:      #52E8C2;   /* Signal Amber — urgency, highlights  */
      --accent-bg:   #FDF3E3;
      --cloud:       #F5F8FB;   /* Cloud — primary background          */
      --steel:       #D7E1EA;   /* Steel Mist — borders, dividers      */
      --graphite:    #1F2A36;   /* Graphite — primary text             */
      --green:       #2DC653;
      --red:         #C94B4B;
      --text:        #1F2A36;
      --text-2:      #4A5568;
      --text-3:      #8A9BB0;
      --border:      #D7E1EA;
      --surface:     #F5F8FB;
      --white:       #FFFFFF;
      --pink:        #0F8A83;
      --pink-dark:   #0A6B65;
      --pink-mist:   #DDF4F1;
      --trust:       #17324D;
      --cyan:        #0F8A83;
      --amber:       #52E8C2;
      --radius-sm:   10px;
      --radius:      12px;
      --radius-lg:   18px;
      --shadow-sm:   0 1px 3px rgba(23,50,77,.07);
      --shadow:      0 4px 16px rgba(23,50,77,.10);
      --shadow-lg:   0 8px 32px rgba(23,50,77,.14);
    }

    html, body {
      font-family: 'Inter', sans-serif;
      background: var(--white);
      width: 100%;
      height: 100%;
      overflow: hidden;
      display: flex;
      flex-direction: column;
    }

    /* Phone shell — always fills exact screen */
    .phone-shell {
      width: 100vw;
      height: calc(var(--app-h, 100vh));
      background: var(--white);
      display: flex;
      flex-direction: column;
      position: relative;
      overflow: hidden;
    }

    /* Mini audio-intro bar — Telegram-style "now playing" lockup. Positioned
       against #screen-building (see its position:relative below), NOT
       against .s1-hero, so the navy banner is purely a background layer
       and this bar floats in front of it as an independent top layer
       instead of being nested/clipped inside the navy box. UI only for
       now; lbToggleAudioBar() in the HTML fakes progress until a real
       <audio> source is wired up. */
    .s1-audio-bar {
      position: absolute;
      top: calc(clamp(24px, 4.5vh, 40px) - 19px);
      left: clamp(12px, 4vw, 20px);
      right: clamp(12px, 4vw, 20px);
      z-index: 15;
      display: flex; align-items: center; gap: 14px;
      padding: 6px 14px;
      background: #fff;
      border-radius: 16px;
      box-shadow: 0 4px 14px rgba(0,0,0,.18);
    }
    .s1-audio-play {
      flex-shrink: 0;
      width: 40px; height: 40px;
      background: var(--teal);
      border: none; border-radius: 50%;
      display: flex; align-items: center; justify-content: center;
      cursor: pointer;
    }
    .s1-audio-info { flex: 1; min-width: 0; }
    .s1-audio-title {
      font-size: 13.5px; font-weight: 700; color: var(--navy);
      line-height: 1.3;
      white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
      margin-bottom: 7px;
    }
    /* Telegram-style scrubber: thicker two-tone track (solid teal played /
       pale teal remaining) with a round thumb, mm:ss labels below. The
       track itself stays a real, always-visible 5px bar; ::before adds an
       invisible taller hit area on top of it (rather than negative-margin
       padding, which was collapsing the flex item down to 0 height and
       hiding the line entirely) so it's still easy to grab on a touchscreen. */
    .s1-audio-progress {
      position: relative;
      height: 5px; border-radius: 99px; background: var(--teal-light, #DDF4F1);
      cursor: pointer; touch-action: none;
    }
    .s1-audio-progress::before {
      content: '';
      position: absolute;
      top: -8px; bottom: -8px; left: 0; right: 0;
    }
    .s1-audio-progress-fill { height: 100%; width: 0%; background: var(--teal); border-radius: 99px; transition: width .25s linear; }
    .s1-audio-thumb {
      position: absolute; top: 50%; left: 0%;
      width: 15px; height: 15px;
      background: var(--teal);
      border-radius: 50%;
      box-shadow: 0 1px 3px rgba(0,0,0,.3);
      transform: translate(-50%, -50%);
      pointer-events: none;
      transition: left .25s linear;
    }
    .s1-audio-times {
      display: flex; justify-content: space-between;
      font-size: 11px; color: var(--text-3, #8a8f98);
      margin-top: 5px;
    }
    .s1-audio-close {
      flex-shrink: 0;
      width: 28px; height: 28px;
      background: none; border: none;
      color: var(--text-3, #8a8f98);
      display: flex; align-items: center; justify-content: center;
      cursor: pointer;
    }

    /* ── Screen system ── */
    .screen {
      display: none;
      flex-direction: column;
      flex: 1;
      min-height: 0;
      width: 100%;
      overflow-y: auto;
      overflow-x: hidden;
      -webkit-overflow-scrolling: touch;
      animation: fadeIn .25s ease;
    }
    .screen.active { display: flex; }

    /* Anchors .s1-audio-bar's position:absolute here instead of it falling
       back to the document root (which would break its scroll behavior
       inside this screen's own scroll container). */
    #screen-building { position: relative; }

    /* Catalogue gate — no building selected yet: screen-grid shows only the
       hero. JS toggles .lb-gate on #screen-grid (see updateHeroCta()). */
    #screen-grid.lb-gate .banner-desktop,
    #screen-grid.lb-gate .lb-cat-showcase,
    #screen-grid.lb-gate .cats-wrap,
    #screen-grid.lb-gate .grid-wrap { display: none !important; }

    /* main-content must be a bounded flex container on ALL screen sizes for scroll to work */
    .main-content {
      flex: 1;
      display: flex;
      flex-direction: column;
      overflow: hidden;
      min-height: 0;
    }

    @keyframes fadeIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }
    @keyframes slideUp { from { opacity: 0; transform: translateY(24px); } to { opacity: 1; transform: translateY(0); } }

    /* ════════════════════════════════════════
       SCREEN 1 — BUILDING SELECTION
    ════════════════════════════════════════ */

    /* Hero header */
    .s1-hero {
      background: linear-gradient(135deg, var(--navy) 0%, var(--harbor) 100%);
      padding: clamp(28px, 6vh, 56px) clamp(16px, 5vw, 28px) clamp(20px, 4vh, 36px);
      transition: padding-top .2s ease;
      position: relative;
      overflow: hidden;
      flex-shrink: 0;
    }

    .s1-hero::before {
      content: '';
      position: absolute;
      top: -40px; right: -40px;
      width: 180px; height: 180px;
      background: rgba(255,255,255,.06);
      border-radius: 50%;
    }

    .s1-hero::after {
      content: '';
      position: absolute;
      bottom: -60px; left: -20px;
      width: 140px; height: 140px;
      background: rgba(255,255,255,.04);
      border-radius: 50%;
    }

    .logo {
      display: flex;
      align-items: center;
      gap: 10px;
      margin-bottom: clamp(14px, 3vh, 28px);
    }

    /* Full horizontal lockup (icon + wordmark + tagline) replaces the old
       small icon + "Lobbybuy" text mark. Two versions swap by breakpoint:
       white-on-transparent for the mobile navy gradient hero, and the
       navy-text version for the desktop light-mint hero. */
    .s1-logo-full { height: 51px; width: auto; display: block; }
    .s1-logo-full-desktop { display: none; }

    .s1-title { font-size: clamp(20px, 5vw, 28px); font-weight: 800; color: white; line-height: 1.2; margin-bottom: 6px; }
    .s1-sub { font-size: clamp(11px, 3vw, 14px); color: rgba(255,255,255,.7); font-weight: 400; }

    /* Bottom-of-page prompt — sends visitors who've read the whole explainer
       and still have questions straight into chat, instead of only being
       reachable from the header. A plain text link (not a button/card) with
       an animated underline so it feels inviting without competing with the
       real CTA (the postal search up top). */
    .s1-help-link {
      display: flex; align-items: center; justify-content: center; gap: 6px;
      margin-top: clamp(6px, 1.5vh, 14px);
      padding: 4px 0 2px;
      background: none; border: none;
      font-size: 14px; font-weight: 700; color: var(--teal-dark, var(--teal));
      cursor: pointer;
      background-image: linear-gradient(var(--teal), var(--teal));
      background-repeat: no-repeat;
      background-position: bottom left;
      background-size: 0% 1.5px;
      transition: background-size .25s ease, color .15s ease;
      width: fit-content;
      margin-left: auto; margin-right: auto;
    }
    .s1-help-link:hover { background-size: 100% 1.5px; color: var(--teal); }

    /* Search area */
    /* overflow-y is intentionally NOT set here — .screen (the ancestor) is
       already the single scroll container for this page. A second nested
       overflow:auto here fights it on iOS Safari (touch gets captured by
       whichever container the finger lands on first) and can make the page
       feel like it doesn't scroll at all. flex:none keeps this box at its
       natural content height so .screen's own scroll sees the full page. */
    .s1-body { padding: clamp(16px, 3vh, 28px) clamp(14px, 5vw, 24px); display: flex; flex-direction: column; gap: clamp(10px, 2vh, 18px); flex: none; background: var(--surface); }

    /* Mobile-only "enter your postal code" prompt — the desktop hero has its
       own floating card that says the same thing (#screen-building
       .s1-hero-visual .s1-hv-float, hidden on mobile), so this is the
       mobile equivalent. Hidden on desktop below to avoid saying it twice. */
    .s1-search-label {
      display: flex; align-items: center; gap: 6px;
      font-size: 14px; font-weight: 700; color: var(--teal);
    }
    .s1-search-label-icon { font-size: 15px; }

    .search-wrap {
      position: relative;
    }

    .search-icon {
      position: absolute; left: 16px; top: 50%; transform: translateY(-50%);
      color: var(--text-3); pointer-events: none;
    }

    /* Bolder than a generic search box — this is the single action on the
       page, not a filter, so it needs to read as the obvious next step.
       font-size 16px also stops iOS Safari's auto-zoom-on-focus (anything
       under 16px triggers it), which was adding to the "confusing" feel by
       jumping the whole page when the keyboard opened. */
    .search-input {
      width: 100%;
      padding: 15px 16px 15px 46px;
      background: var(--white);
      border: 2px solid var(--teal);
      border-radius: var(--radius);
      font-family: 'Inter', sans-serif;
      font-size: 16px;
      font-weight: 600;
      color: var(--text);
      outline: none;
      box-shadow: 0 6px 18px -8px rgba(15,138,131,.35);
      transition: border-color .2s, box-shadow .2s;
    }

    .search-input:focus {
      border-color: var(--teal);
      box-shadow: 0 0 0 3px rgba(15,138,131,.18);
    }

    /* text-transform:uppercase on the input (inline, for what the resident
       types) would otherwise also shout the placeholder's "e.g." — reset it
       here so only the typed postal code gets uppercased. */
    .search-input::placeholder { color: var(--text-3); font-weight: 400; text-transform: none; }

    /* Mobile warehouse-direct explainer card (fills empty first screen) */
    .s1-concept {
      --lbh-deep:#073B39; --lbh-teal:#0A4A47; --lbh-mint:#3FE3C1; --lbh-ink:#0B2E2B;
      --lbh-em:#0F9E7E; --lbh-tint:#EAF7F3; --lbh-line:#DCEBE7; --lbh-muted:#6A8480;
      margin-top: 4px; padding: 20px 18px 22px;
      background: #F4FBF9; border: 1px solid var(--lbh-line); border-radius: 18px;
      position: relative; overflow: hidden;
    }
    .s1-concept::after {
      content: ''; position: absolute; inset: 0; pointer-events: none;
      background: radial-gradient(360px 200px at 80% 6%, rgba(63,227,193,.20), transparent 70%);
    }
    .s1-concept-scene { position: relative; z-index: 1; }
    .s1-concept-scene svg { width: 100%; height: auto; display: block; }
    /* shadow on the structure groups only — a filter on the whole <svg> would
       also ghost the brand lockup <image> sitting under the ground line */
    .s1-concept-scene svg > g { filter: drop-shadow(0 8px 16px rgba(7,59,57,.14)); }
    .s1-route { stroke-dasharray: 7 7; animation: lb-route-flow 1.1s linear infinite; }
    .s1-route-marker { stroke: #fff; stroke-width: 1; filter: drop-shadow(0 2px 4px rgba(7,59,57,.4)); }
    .s1-route-word {
      font-family: 'Inter', sans-serif; font-size: 15px; font-weight: 800;
      letter-spacing: 4px; fill: #5CEBCE; text-transform: uppercase; text-anchor: middle;
      paint-order: stroke; stroke: #073B39; stroke-width: 4px; stroke-linejoin: round;
    }
    .s1-concept-title {
      position: relative; z-index: 1; margin-top: 14px;
      font-size: 19px; font-weight: 800; color: var(--lbh-ink); line-height: 1.22; letter-spacing: -.4px;
    }
    .s1-concept-title em { color: var(--lbh-em); font-style: normal; }
    .s1-concept-sub {
      position: relative; z-index: 1; margin-top: 8px;
      font-size: 13.5px; color: var(--lbh-muted); line-height: 1.55;
    }
    .s1-concept-feats {
      position: relative; z-index: 1; margin-top: 16px;
      display: flex; flex-direction: column; gap: 10px;
    }
    .s1-cf { display: flex; align-items: center; gap: 11px; font-size: 13.5px; font-weight: 700; color: var(--lbh-ink); }
    .s1-cf-ic {
      width: 34px; height: 34px; border-radius: 9px; background: var(--lbh-tint);
      display: flex; align-items: center; justify-content: center; font-size: 17px; flex-shrink: 0;
    }
    @keyframes lb-route-flow { to { stroke-dashoffset: -28; } }


    /* Divider */
    .divider {
      display: flex; align-items: center; gap: 12px;
      font-size: 12px; font-weight: 500; color: var(--text-3);
    }
    .divider::before, .divider::after { content:''; flex:1; height:1px; background:var(--border); }

    /* Section label */
    .sec-label {
      font-size: 11px; font-weight: 700; color: var(--text-3);
      text-transform: uppercase; letter-spacing: .8px;
    }

    /* Building cards */
    .buildings-list { display: flex; flex-direction: column; gap: 10px; }

    .building-card {
      display: flex; align-items: center; gap: 14px;
      padding: 14px 16px;
      background: var(--white);
      border: 1.5px solid var(--border);
      border-radius: var(--radius);
      cursor: pointer;
      box-shadow: var(--shadow-sm);
      transition: all .2s;
    }

    .building-card:hover { border-color: var(--teal); transform: translateY(-1px); box-shadow: var(--shadow); }

    .building-ava {
      width: 44px; height: 44px;
      background: var(--teal-light);
      border-radius: var(--radius-sm);
      display: flex; align-items: center; justify-content: center;
      font-size: 22px; flex-shrink: 0;
    }

    .building-info { flex: 1; min-width: 0; }
    .building-name { font-size: 14px; font-weight: 600; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    .building-addr { font-size: 12px; color: var(--text-3); margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

    .building-tag {
      font-size: 11px; font-weight: 600;
      padding: 3px 9px; border-radius: 20px; white-space: nowrap;
    }

    .tag-active { background: #DCFCE7; color: #166534; }
    .tag-soon   { background: var(--accent-bg); color: #92400E; }

    .chevron-icon { color: var(--text-3); flex-shrink: 0; }

    /* Search results */
    .search-results { display: none; flex-direction: column; gap: 8px; }
    .search-results.visible { display: flex; }

    /* ════════════════════════════════════════
       SCREEN 2 — PRODUCT GRID
    ════════════════════════════════════════ */

    /* Top bar */
    .topbar {
      background: linear-gradient(135deg, var(--navy) 0%, var(--harbor) 100%);
      padding: 10px var(--side-pad, 14px) 10px;
      width: 100%;
      padding-top: calc(10px + env(safe-area-inset-top, 0px));
    }

    .topbar-row1 {
      display: flex; align-items: center; justify-content: space-between;
      width: 100%;
      margin-bottom: 8px;
    }

    .building-pill {
      display: flex; align-items: center; gap: 6px;
      background: rgba(255,255,255,.15);
      border: 1px solid rgba(255,255,255,.25);
      border-radius: 99px;
      padding: 5px 12px;
      cursor: pointer;
      transition: background .2s;
    }

    .building-pill:hover { background: rgba(255,255,255,.25); }
    .building-pill span { font-size: 13px; font-weight: 600; color: white; }

    .topbar-icons { display: flex; gap: 14px; }

    .icon-btn {
      width: 34px; height: 34px;
      background: rgba(255,255,255,.12);
      border: 1px solid rgba(255,255,255,.2);
      border-radius: 10px;
      display: flex; align-items: center; justify-content: center;
      cursor: pointer; position: relative;
    }

    .icon-btn svg { width: 17px; height: 17px; stroke: white; }

    .notif-dot {
      position: absolute; top: 6px; right: 6px;
      width: 7px; height: 7px;
      background: var(--accent);
      border-radius: 50%;
      border: 1.5px solid var(--teal);
    }

    /* Search bar in topbar */
    .topbar-search {
      display: flex; align-items: center; gap: 8px;
      background: white;
      border-radius: 10px;
      padding: 7px 12px;
      width: 100%;
    }

    .topbar-search input {
      border: none; outline: none;
      font-family: 'Inter', sans-serif;
      font-size: 13px; color: var(--text);
      flex: 1; background: transparent;
    }

    .topbar-search input::placeholder { color: var(--text-3); }

    /* Banner — split card: message panel left, countdown stat panel right.
       Shares the navy→teal gradient language of the building-selection card. */
    .banner {
      background: linear-gradient(135deg, var(--navy) 0%, var(--teal) 100%);
      margin: 10px var(--side-pad, 12px) 0;
      border-radius: var(--radius-lg);
      display: flex; align-items: stretch;
      position: relative; overflow: hidden;
      min-height: var(--banner-h, 22vh);
      color: white;
      box-shadow: 0 8px 22px rgba(15,138,131,.28);
    }

    .banner-main {
      flex: 1; min-width: 0;
      padding: var(--side-pad, 10px);
      display: flex; flex-direction: column;
      justify-content: space-between;
      gap: clamp(8px, 1.6vh, 16px);
    }

    .banner-pill {
      display: inline-block;
      background: rgba(255,255,255,.18);
      font-size: 10.5px; font-weight: 700;
      padding: 3px 10px; border-radius: 999px;
      margin-bottom: clamp(5px, 1vh, 10px);
    }

    .banner-title { font-size: clamp(15px, 2vh, 18px); font-weight: 800; color: white; line-height: 1.25; margin-bottom: 0; }

    .banner-meta { font-size: 11.5px; color: rgba(255,255,255,.82); margin-top: clamp(4px, 0.8vh, 8px); }
    .banner-meta b { color: white; }

    .banner-btn {
      align-self: flex-start;
      background: white;
      color: var(--navy);
      font-family: 'Inter', sans-serif;
      font-size: 11px; font-weight: 800;
      border: none; border-radius: 99px;
      padding: 8px 14px; cursor: pointer;
      white-space: nowrap;
      transition: opacity .2s;
    }

    .banner-btn:hover { opacity: .9; }

    .banner-stat-panel {
      flex-shrink: 0; width: 108px;
      background: rgba(0,0,0,.22);
      display: flex; flex-direction: column;
      align-items: center; justify-content: center;
      gap: 2px; padding: 14px 10px;
      text-align: center;
    }

    .cd-days { font-size: 34px; font-weight: 900; line-height: 1; }
    .cd-days.urgent { color: #FFD66B; }
    .cd-days-label { font-size: 10.5px; font-weight: 700; opacity: .85; line-height: 1.35; }
    .banner-stat-divider { width: 60%; height: 1px; background: rgba(255,255,255,.2); margin: 8px 0; }
    .banner-stat-deliv { font-size: 11px; font-weight: 700; opacity: .9; }

    /* Skeleton state for banner date/countdown values while startCountdown()
       is still fetching real event data — avoids painting the hardcoded
       "Jun 15" / "Jun 16" placeholder text baked into the markup before the
       real dates arrive. countdown.js adds this class to close-date/
       deliv-date/cd-days/countdown-timer on load and removes it once it has
       real values to show (see run()/renderClosed() in countdown.js). */
    .lb-skel {
      color: transparent !important;
      background: linear-gradient(90deg, rgba(255,255,255,.22) 25%, rgba(255,255,255,.42) 37%, rgba(255,255,255,.22) 63%);
      background-size: 400% 100%;
      animation: lbSkelShimmer 1.3s ease infinite;
      border-radius: 4px;
      display: inline-block;
      min-width: 34px;
    }
    .cd-days.lb-skel { min-width: 28px; }
    @keyframes lbSkelShimmer {
      0% { background-position: 100% 0; }
      100% { background-position: 0 0; }
    }


    /* Categories */
    .cats-wrap { padding: 10px var(--side-pad,12px) 6px; position: relative; }
    .cats-wrap::after {
      content: '';
      position: absolute; top: 0; right: 0; bottom: 6px;
      width: 40px;
      background: linear-gradient(to left, var(--white) 0%, transparent 100%);
      pointer-events: none;
      z-index: 2;
    }
    .cats-title { font-size: 10px; font-weight: 700; color: var(--text-3); text-transform: uppercase; letter-spacing: .8px; margin-bottom: 8px; }

    /* Horizontal scroll dots */
    .cats-dots {
      display: flex;
      justify-content: center;
      align-items: center;
      gap: 5px;
      margin-top: 8px;
    }
    .cats-dot {
      width: 5px; height: 5px;
      border-radius: 50%;
      background: var(--border);
      transition: background .2s, transform .2s;
    }
    .cats-dot.active {
      background: var(--teal);
      transform: scale(1.3);
    }
    .cats {
      display: grid;
      grid-template-rows: repeat(2, auto);
      grid-auto-flow: column;
      grid-auto-columns: 74px;   /* fixes each column width so grid expands rightward */
      gap: 12px 14px;
      overflow-x: auto;
      overflow-y: visible;
      width: 100%;
      scrollbar-width: none;
      padding-bottom: 4px;
      -webkit-overflow-scrolling: touch;
    }
    .cats::-webkit-scrollbar { display: none; }

    .cat {
      display: flex; flex-direction: column; align-items: center; gap: 5px;
      width: 82px; min-width: 74px; cursor: pointer; flex-shrink: 0;
    }

    .cat-circle {
      width: 58px; height: 58px; border-radius: 50%;
      background: var(--white);
      border: 1.5px solid var(--border);
      display: flex; align-items: center; justify-content: center;
      font-size: 26px;
      transition: all .2s;
    }

    .cat.active .cat-circle { background: var(--teal-light); border-color: var(--teal); }

    /* Photo variant: the catalog image fills the circle edge to edge, so the
       white fill and the emoji's font-size are irrelevant and the border becomes
       a hairline ring over the photo rather than a box around an emoji. */
    .cat-circle.has-photo {
      overflow: hidden;
      padding: 0;
      background: var(--teal-pale);
      border-color: rgba(0, 0, 0, .06);
      box-shadow: 0 1px 3px rgba(0, 0, 0, .08);
    }
    .cat-circle.has-photo img { border-radius: 50%; }
    .cat:hover .cat-circle.has-photo { box-shadow: 0 3px 10px rgba(0, 0, 0, .14); }
    /* Active state can no longer be a background swap (the photo covers it), so
       it reads as a teal ring drawn outside the image instead. */
    .cat.active .cat-circle.has-photo {
      border-color: var(--teal);
      box-shadow: 0 0 0 2px var(--teal-light);
    }

    /* Avatar on the "all categories" grid cards (#cat-grid-cards). Same circular
       treatment as the strip, one size up because the card has room for it.
       Without a photo it falls back to the emoji at its original 36px. */
    .cat-grid-avatar {
      width: 56px; height: 56px;
      display: flex; align-items: center; justify-content: center;
      font-size: 36px; line-height: 1;
    }
    .cat-grid-avatar.has-photo {
      border-radius: 50%; overflow: hidden;
      background: var(--teal-pale);
      box-shadow: 0 1px 4px rgba(0, 0, 0, .1), inset 0 0 0 1px rgba(0, 0, 0, .05);
    }

    /* Hide the horizontal scrollbar on the related-products row (desktop Chrome/Safari;
       Firefox uses scrollbar-width:none inline). Scroll still works. */
    #pd-related-row::-webkit-scrollbar { display: none; }

    .cat-label {
      font-size: 13px; font-weight: 600; color: var(--text-3); text-align: center;
      width: 100%; line-height: 1.25; min-height: 33px;      /* reserve 2 lines so circles stay aligned */
      white-space: normal; overflow-wrap: anywhere; word-break: break-word;
      display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
    }
    .cat.active .cat-label { color: var(--teal); font-weight: 700; }

    /* Product grid */
    .grid-wrap { padding: 8px var(--side-pad, 12px) calc(var(--nav-h, 64px) + 16px); width: 100%; }
    .grid-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
    .grid-title { font-size: 14px; font-weight: 700; color: var(--text); }
    .grid-count { font-size: 12px; color: var(--text-3); }

    .grid {
      display: grid;
      grid-template-columns: repeat(2, 1fr);
      gap: var(--grid-gap, 10px);
    }

    .pcard {
      background: var(--white);
      border: 1.5px solid var(--border);
      border-radius: var(--radius);
      overflow: hidden;
      cursor: pointer;
      box-shadow: var(--shadow-sm);
      transition: all .2s;
      display: flex;
      flex-direction: column;
      /* Skip layout/paint for cards scrolled off-screen in the long product grid.
         `auto` lets the browser remember each card's real size after first render,
         so the scrollbar doesn't jump. Falls back gracefully where unsupported. */
      content-visibility: auto;
      contain-intrinsic-size: auto 280px;
    }

    .pcard:hover { transform: translateY(-2px); box-shadow: var(--shadow); border-color: var(--teal); }

    .pcard-img {
      background: var(--surface);
      height: var(--card-img-h, 140px);
      display: flex; align-items: center; justify-content: center;
      font-size: 52px;
      position: relative;
      flex-shrink: 0;
      overflow: hidden;
    }

    .pcard-badge {
      position: absolute; top: 8px; left: 8px;
      background: var(--teal);
      color: white;
      font-size: 10px; font-weight: 600;
      letter-spacing: .2px;
      padding: 4px 9px; border-radius: 99px;
    }

    .pcard-badge.best { background: var(--green); }

    .pcard-body { padding: 12px; display: flex; flex-direction: column; }

    .pcard-name {
      font-size: 13px; font-weight: 600; color: var(--text);
      line-height: 1.4;
      min-height: 36px;
      display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
      overflow: hidden;
      margin-bottom: 3px;
    }

    .pcard-brand {
      font-size: 11px; font-weight: 400; color: var(--text-3);
      white-space: nowrap; text-overflow: ellipsis; overflow: hidden;
      margin-bottom: 6px;
    }

    .pcard-price {
      font-size: 20px; font-weight: 800; color: var(--teal);
      margin-bottom: 2px;
      letter-spacing: -.3px;
    }
    .pcard-price.unlocked { color: var(--green); }

    .pcard-next {
      font-size: 12px; font-weight: 600; color: #92400E;
      white-space: nowrap; text-overflow: ellipsis; overflow: hidden;
      margin-bottom: 8px;
    }
    .pcard-next.best-price { color: var(--green); }

    .pcard-unlocked-banner {
      background: var(--teal-pale);
      border-radius: 8px;
      padding: 6px 8px;
      margin-bottom: 8px;
    }
    .pcard-unlocked-banner .row1 { display: flex; align-items: center; gap: 5px; }
    .pcard-unlocked-banner .icon { color: var(--green); font-size: 13px; flex-shrink: 0; line-height: 1; }
    .pcard-unlocked-banner .label { font-size: 11px; font-weight: 600; color: var(--green); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    .pcard-unlocked-banner .prev-price {
      font-size: 11px; font-weight: 600; color: var(--text-3);
      text-decoration: line-through;
      margin-top: 2px;
      margin-left: 18px;
      white-space: nowrap;
    }

    /* Interactive tier bar */
    .pcard-pbar-wrap {
      user-select: none;
      -webkit-user-select: none;
      margin-top: 6px;
    }
    .pcard-pbar-row {
      display: flex;
      align-items: center;
      gap: 8px;
    }
    .pcard-pbar-track {
      position: relative;
      flex: 1;
      background: var(--border);
      border-radius: 99px;
      height: 4px;
    }
    .pcard-pbar-fill {
      height: 4px;
      border-radius: 99px;
      background: linear-gradient(90deg, var(--teal), #52b788);
      pointer-events: none;
    }
    .pcard-pbar-fill.unlocked { background: var(--green); }
    .pcard-pbar-thumb {
      position: absolute;
      top: 50%;
      transform: translate(-50%, -50%) rotate(45deg);
      width: 14px; height: 14px;
      background: var(--teal);
      border: 2.5px solid white;
      border-radius: 2px;
      box-shadow: 0 1px 5px rgba(0,0,0,.22);
      cursor: grab;
      touch-action: none;
    }
    .pcard-pbar-thumb.unlocked { background: var(--green); }
    .pcard-pbar-thumb:active { cursor: grabbing; transform: translate(-50%, -50%) rotate(45deg) scale(1.2); }
    .pcard-pbar-label {
      text-align: center;
      font-size: 11px; font-weight: 600;
      color: #0369A1;
      margin-top: 5px;
    }
    .pcard-pbar-label.unlocked { color: var(--green); }

    .pcard-pbar-goal {
      font-size: 16px; font-weight: 800;
      color: #c0cece;
      white-space: nowrap;
      flex-shrink: 0;
      letter-spacing: -.3px;
    }
    @keyframes price-flash {
      0%   { color: var(--green); transform: scale(1); }
      20%  { color: #a7f3d0;      transform: scale(1.25); }
      40%  { color: var(--green); transform: scale(1); }
      60%  { color: #a7f3d0;      transform: scale(1.18); }
      80%  { color: var(--green); transform: scale(1.05); }
      100% { color: var(--green); transform: scale(1); }
    }
    .pcard-pbar-goal.unlocked {
      animation: price-flash .6s ease forwards;
    }

    /* ────────────────────────────────────────────────────────────────
       PRODUCT DETAIL — base (mobile) rules.
       These values were LIFTED VERBATIM out of the inline style="" attrs
       that used to sit on the same nodes in lobbybuy.html / related.js, so
       mobile renders pixel-identically. They exist as classes only so the
       desktop block (min-width:768px) can restyle them without needing an
       !important on every single declaration.
       ──────────────────────────────────────────────────────────────── */
    .pd-brand { font-size: 10px; font-weight: 600; color: var(--text-3); text-transform: uppercase; letter-spacing: .6px; }
    .pd-title { font-size: 18px; font-weight: 700; color: var(--text); margin-top: 4px; line-height: 1.3; }
    .pd-price-block { margin-top: 10px; }
    .pd-price { font-size: 28px; font-weight: 800; color: var(--teal); }
    .pd-price-note { display: none; }            /* desktop-only sub-label */
    .pd-sec-h { font-size: 12px; font-weight: 700; color: var(--text); margin-bottom: 12px; }
    .pd-tier-msg { font-size: 13px; color: var(--text-2); line-height: 1.6; margin-bottom: 14px; }
    .pd-block-h {
      font-size: 11px; font-weight: 700; color: var(--text-3);
      text-transform: uppercase; letter-spacing: .6px; margin-bottom: 8px;
    }
    #pd-description { font-size: 13px; color: var(--text-2); line-height: 1.65; }
    .pd-related-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }

    /* Desktop-only buy-box extras (price echo + reassurance list) */
    .pd-buybox-extra { display: none; }

    /* Related-product cards */
    .pd-rel-card {
      flex: 0 0 132px;
      background: white; border: 1px solid var(--border);
      border-radius: 12px; overflow: hidden; cursor: pointer;
    }
    .pd-rel-media {
      height: 96px; background: var(--surface);
      display: flex; align-items: center; justify-content: center; overflow: hidden;
    }
    .pd-rel-body { padding: 8px 10px; }
    .pd-rel-brand {
      font-size: 11px; color: var(--text-3); font-weight: 600;
      white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    }
    .pd-rel-name {
      font-size: 12px; font-weight: 600; color: var(--text); line-height: 1.3;
      height: 31px; overflow: hidden;
      display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    }
    .pd-rel-price { font-size: 14px; font-weight: 800; color: var(--teal); margin-top: 4px; }

    /* Image lightbox */
    #img-lightbox {
      display: none;
      position: fixed;
      inset: 0;
      z-index: 9999;
      background: rgba(0,0,0,.85);
      align-items: center;
      justify-content: center;
    }
    #img-lightbox.open { display: flex; }
    #img-lightbox-inner {
      position: relative;
      max-width: 92vw;
      max-height: 88vh;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    #img-lightbox img {
      max-width: 92vw;
      max-height: 80vh;
      object-fit: contain;
      border-radius: 12px;
    }
    #img-lightbox-close {
      position: absolute;
      top: -14px;
      right: -14px;
      width: 32px; height: 32px;
      border-radius: 50%;
      background: white;
      border: none;
      font-size: 18px;
      line-height: 32px;
      text-align: center;
      cursor: pointer;
      box-shadow: 0 2px 8px rgba(0,0,0,.3);
    }

    /* Bubble above thumb */
    .pcard-pbar-bubble {
      position: absolute;
      bottom: calc(100% + 8px);
      left: 50%;
      transform: translateX(-50%) scale(0);
      transform-origin: bottom center;
      background: var(--navy);
      color: white;
      font-size: 11px; font-weight: 700;
      padding: 4px 9px;
      border-radius: 8px;
      white-space: nowrap;
      pointer-events: none;
      opacity: 0;
      transition: transform .15s cubic-bezier(.34,1.56,.64,1), opacity .15s;
    }
    .pcard-pbar-bubble::after {
      content: '';
      position: absolute;
      top: 100%; left: 50%;
      transform: translateX(-50%);
      border: 5px solid transparent;
      border-top-color: var(--navy);
    }
    .pcard-pbar-bubble.visible {
      transform: translateX(-50%) scale(1);
      opacity: 1;
    }

    .pbar-tick { position: absolute; top: -2px; width: 1px; height: 8px; background: var(--bg); opacity: .5; pointer-events: none; transform: translateX(-50%); }
    .pbar-bg { background: var(--border); border-radius: 99px; height: 4px; }
    .pbar-fill { height: 4px; border-radius: 99px; transition: width .4s ease; }
    .pbar-teal  { background: linear-gradient(90deg, var(--teal), #52b788); }
    .pbar-green { background: var(--green); }


    /* Floating chat button */
    .fab {
      position: fixed;
      bottom: 80px; right: 50%;
      transform: translateX(calc(195px));
      width: 52px; height: 52px;
      background: linear-gradient(135deg, var(--teal), var(--teal-dark));
      border-radius: 50%;
      box-shadow: 0 4px 20px rgba(10,147,150,.4);
      display: flex; align-items: center; justify-content: center;
      cursor: pointer;
      z-index: 50;
      transition: transform .2s, box-shadow .2s;
      border: none;
    }

    .fab:hover { transform: translateX(calc(195px)) scale(1.08); box-shadow: 0 6px 24px rgba(10,147,150,.5); }
    .fab svg { width: 22px; height: 22px; stroke: white; }

    /* Second half of the selector = the portrait-lock case: a sideways phone
       reports a WIDTH of ~700-950px, so max-width:480px would stop matching
       and these phone rules would silently switch off mid-rotation. */
    @media (max-width: 480px),
           (orientation: landscape) and (max-height: 500px) {
      .fab { right: 20px; transform: none; }
      .fab:hover { transform: scale(1.08); }
    }

    /* Bottom nav */
    /* Full multi-column page footer (brand / explore / support columns +
       bottom bar) — scrolls into view at the natural end of each screen's
       content. NOT fixed; sits inside the scrollable area, so it never
       competes with .bottom-nav below. The --nav / --cta modifiers add
       extra bottom padding on screens where a fixed .bottom-nav (56px)
       and/or fixed .basket-checkout-bar (~68px) would otherwise cover it.
       Mobile-first: columns stack vertically by default (matching the
       phone-shell's narrow layout) and switch to a 3-column row inside the
       min-width:768px desktop query further down this file. */
    .lb-footer {
      padding: 32px 20px 24px;
      background: var(--navy);
      color: rgba(255,255,255,.65);
      border-top: 3px solid var(--teal);
      flex-shrink: 0;
    }
    .lb-footer-main {
      display: flex;
      flex-direction: column;
      gap: 22px;
      max-width: 1100px;
      margin: 0 auto;
      padding-bottom: 22px;
    }
    .lb-footer-col { display: flex; flex-direction: column; gap: 10px; }
    .lb-footer-logo { display: flex; align-items: center; gap: 8px; }
    /* Full horizontal lockup in place of the old small icon + "Lobbybuy" text —
       same treatment as the select-building hero and desktop header logos. */
    .lb-footer-logo-full { height: 32px; width: auto; display: block; }
    .lb-footer-tagline { font-size: 12px; line-height: 1.6; color: rgba(255,255,255,.65); }
    .lb-footer-heading {
      font-size: 11px; font-weight: 700; color: white;
      text-transform: uppercase; letter-spacing: .6px;
    }
    .lb-footer-col a {
      font-size: 13px;
      color: rgba(255,255,255,.65);
      text-decoration: none;
      transition: color .15s;
    }
    .lb-footer-col a:hover { color: var(--teal-light); text-decoration: underline; }
    .lb-footer-bottom {
      max-width: 1100px;
      margin: 0 auto;
      padding-top: 20px;
      border-top: 1px solid rgba(255,255,255,.12);
      text-align: center;
      font-size: 12px;
      line-height: 1.7;
    }
    .lb-footer-copy { color: rgba(255,255,255,.5); margin-bottom: 6px; }
    .lb-footer-legal a {
      color: rgba(255,255,255,.75);
      text-decoration: none;
      font-weight: 600;
      margin: 0 8px;
      transition: color .15s;
    }
    .lb-footer-legal a:hover { color: var(--teal-light); text-decoration: underline; }
    .lb-footer--nav { padding-bottom: calc(24px + var(--nav-h, 56px)); }
    .lb-footer--cta { padding-bottom: calc(24px + var(--nav-h, 56px) + 68px); }

    .bottom-nav {
      position: fixed; bottom: 0; left: 0;
      width: 100%;
      background: var(--white);
      border-top: 1px solid var(--border);
      display: flex;
      padding: 8px 0 max(16px, env(safe-area-inset-bottom, 16px));
      z-index: 40;
    }

    .nav-item {
      flex: 1; display: flex; flex-direction: column;
      align-items: center; gap: 3px;
      color: var(--text-3); font-size: 10px; font-weight: 500;
      cursor: pointer; transition: color .2s;
    }

    .nav-item.active { color: var(--teal); }
    .nav-item svg { width: 20px; height: 20px; stroke: currentColor; }

    /* How it works — unseen highlight */
    .how-nav.unseen { color: #F59E0B; }
    .how-pulse {
      display: none;
      position: absolute; top: 2px; right: calc(50% - 14px);
      width: 8px; height: 8px; border-radius: 99px;
      background: #F59E0B;
      animation: howPulse 1.4s ease-in-out infinite;
    }
    .how-nav.unseen .how-pulse { display: block; }
    @keyframes howPulse {
      0%,100% { transform: scale(1); opacity: 1; }
      50% { transform: scale(1.6); opacity: .5; }
    }

    /* How it works modal */
    #how-modal {
      display: none; position: fixed; inset: 0; z-index: 100;
      background: rgba(0,0,0,.5); align-items: flex-end; justify-content: center;
    }
    #how-modal.open { display: flex; }
    /* display:flex column so .how-topbar (title/× close) sits outside the
       scrollable area instead of scrolling away with the timeline content —
       only .how-modal-body scrolls, via flex:1 + its own overflow-y below.
       Same split already used by #legal-modal-box/.legal-modal-body. */
    #how-modal-box {
      background: white; border-radius: 20px 20px 0 0;
      width: 100%; max-width: 500px;
      padding: 24px 20px 32px; max-height: 80vh;
      display: flex; flex-direction: column;
    }
    #how-modal-box .how-topbar { flex-shrink: 0; }
    .how-modal-body { flex: 1; min-height: 0; overflow-y: auto; }

    /* Legal / "About Us" modal — identical mobile bottom-sheet shell to
       #how-modal above (see #legal-modal's desktop override next to
       #how-modal's for the slide-in-panel version). */
    #legal-modal {
      display: none; position: fixed; inset: 0; z-index: 100;
      background: rgba(0,0,0,.5); align-items: flex-end; justify-content: center;
    }
    #legal-modal.open { display: flex; }
    /* display:flex column so the topbar (with the back/close buttons) sits
       outside the scrollable area instead of scrolling away with the long
       policy text — only #legal-modal-body scrolls, via flex:1 + its own
       overflow-y below. */
    #legal-modal-box {
      background: white; border-radius: 20px 20px 0 0;
      width: 100%; max-width: 500px;
      padding: 24px 20px 32px; max-height: 80vh;
      display: flex; flex-direction: column;
    }
    #legal-modal-box .how-topbar { flex-shrink: 0; }
    /* Body typography for the injected policy HTML (openLegalModal() sets
       this element's innerHTML from lobbybuy/legal.js's LEGAL_CONTENT). */
    .legal-modal-body {
      font-size: 13px; line-height: 1.7; color: var(--text-2);
      flex: 1; min-height: 0; overflow-y: auto;
    }
    .legal-modal-body h4 {
      font-size: 14px; font-weight: 800; color: var(--navy);
      margin: 18px 0 6px;
    }
    .legal-modal-body h4:first-child { margin-top: 0; }
    .legal-modal-body p { margin: 0 0 10px; }
    .legal-modal-body ol, .legal-modal-body ul { margin: 0 0 10px; padding-left: 20px; }
    .legal-modal-body li { margin-bottom: 4px; }
    .legal-modal-body a { color: var(--teal); }

    /* "About Us" dropdown (desktop-subnav trigger, #dsn-about). Fixed +
       JS-positioned by toggleAboutDropdown() in lobbybuy/legal.js — see that
       function for why it isn't nested/absolutely-positioned inside
       .desktop-subnav instead. Hidden by default on every breakpoint; the
       trigger itself only exists in the desktop subnav, so this never shows
       on mobile. */
    .dsn-dropdown {
      display: none; flex-direction: column;
      position: fixed; z-index: 200;
      background: white; border-radius: 12px;
      box-shadow: 0 10px 30px rgba(0,0,0,.2);
      padding: 6px; min-width: 200px;
    }
    .dsn-dropdown.open { display: flex; }
    .dsn-dropdown a {
      padding: 10px 14px; border-radius: 8px;
      font-size: 13px; font-weight: 600; color: var(--navy);
      text-decoration: none; white-space: nowrap; cursor: pointer;
    }
    .dsn-dropdown a:hover { background: var(--surface); color: var(--teal); }

    /* ════════════════════════════════════════
       SCREEN 3 — CHAT
    ════════════════════════════════════════ */
    .chat-topbar {
      background: linear-gradient(135deg, var(--navy) 0%, var(--harbor) 100%);
      padding: 16px;
      display: flex; align-items: center; gap: 12px;
    }

    /* Orders screen never had a mobile back arrow (bottom-nav handles nav there).
       Keep it hidden by default; the desktop media query turns it on. */
    .orders-back-btn { display: none; }
    /* Profile screen — same treatment as Orders (see .orders-back-btn above):
       no mobile back arrow, bottom-nav handles it; desktop turns it on. */
    .profile-back-btn { display: none; }

    /* Orders screen — nav in-flow so total bar sits naturally above it */
    #screen-orders .bottom-nav {
      position: static;
      width: 100%;
    }
    /* Profile screen — same in-flow nav treatment as Orders above */
    #screen-profile .bottom-nav {
      position: static;
      width: 100%;
    }

    /* Product screen — basket bar + nav in-flow so fixed positioning doesn't break inside overflow container */
    #screen-product .basket-checkout-bar {
      position: static;
      padding: 12px 16px;
      border-top: 1px solid var(--border);
      background: white;
      flex-shrink: 0;
    }
    #screen-product .bottom-nav {
      position: static;
      width: 100%;
    }

    /* Basket checkout bar — fixed on mobile, in-flow on desktop */
    .basket-checkout-bar {
      position: fixed;
      bottom: var(--nav-h, 56px);
      left: 0; right: 0;
      padding: 12px 16px;
      background: white;
      border-top: 1px solid var(--border);
      z-index: 39;
    }

    .back-btn {
      background: rgba(255,255,255,.15);
      border: none; border-radius: 10px;
      width: 34px; height: 34px;
      display: flex; align-items: center; justify-content: center;
      cursor: pointer;
    }

    .back-btn svg { width: 18px; height: 18px; stroke: white; }

    .chat-building { flex: 1; }
    .chat-building-name { font-size: 15px; font-weight: 700; color: white; }
    .chat-building-sub { font-size: 11px; color: rgba(255,255,255,.65); margin-top: 1px; }

    .close-badge {
      font-size: 11px; font-weight: 700;
      background: rgba(255,255,255,.15);
      border: 1px solid rgba(255,255,255,.25);
      color: white; padding: 4px 10px; border-radius: 99px;
    }

    .chat-messages {
      flex: 1; overflow-y: auto;
      padding: 16px; display: flex;
      flex-direction: column; gap: 12px;
      background: var(--surface);
    }

    .msg { display: flex; flex-direction: column; max-width: 88%; }
    .msg.bot { align-self: flex-start; }
    .msg.user { align-self: flex-end; }

    .msg-bubble {
      padding: 10px 14px; border-radius: 16px;
      font-size: 14px; line-height: 1.55;
    }

    .msg.bot .msg-bubble {
      background: var(--white); color: var(--text);
      border-bottom-left-radius: 4px;
      box-shadow: var(--shadow-sm);
    }

    .msg.user .msg-bubble {
      background: var(--teal); color: white;
      border-bottom-right-radius: 4px;
    }

    /* Chat product card */
    .chat-pcard {
      background: var(--white);
      border: 1.5px solid var(--border);
      border-radius: var(--radius);
      overflow: hidden;
      margin-top: 6px;
      box-shadow: var(--shadow-sm);
    }

    .chat-pcard-head { padding: 12px 12px 8px; }
    .chat-pcard-name { font-size: 13px; font-weight: 700; color: var(--text); }
    .chat-pcard-brand { font-size: 11px; color: var(--text-3); margin-top: 2px; }

    .chat-pricing {
      display: flex; align-items: baseline; gap: 8px; margin-top: 8px;
    }

    .chat-price-group { font-size: 18px; font-weight: 700; color: var(--teal); }
    .chat-price-retail { font-size: 13px; color: var(--text-3); text-decoration: line-through; }
    .chat-save-badge {
      font-size: 11px; font-weight: 700;
      background: #DCFCE7; color: #166534;
      padding: 2px 8px; border-radius: 99px;
    }

    .chat-pcard-progress { padding: 0 12px 12px; }

    .prog-labels {
      display: flex; justify-content: space-between;
      font-size: 11px; color: var(--text-3); margin-bottom: 5px;
    }

    .prog-bar { height: 6px; background: var(--border); border-radius: 99px; overflow: hidden; }
    .prog-fill { height: 100%; border-radius: 99px; background: linear-gradient(90deg, var(--teal), #52b788); }
    .prog-next { font-size: 11px; font-weight: 600; color: var(--teal-dark); margin-top: 5px; }

    .add-btn {
      width: 100%; padding: 12px;
      background: var(--teal);
      color: white; border: none;
      font-family: 'Inter', sans-serif;
      font-size: 14px; font-weight: 700;
      cursor: pointer; transition: opacity .2s;
    }

    .add-btn:hover { opacity: .9; }

    .chat-input-bar {
      display: flex; align-items: center; gap: 10px;
      padding: 12px 16px;
      border-top: 1px solid var(--border);
      background: var(--white);
    }

    .chat-input {
      flex: 1; padding: 10px 14px;
      border: 1.5px solid var(--border);
      border-radius: 24px;
      font-family: 'Inter', sans-serif;
      font-size: 14px; outline: none;
      transition: border-color .2s;
    }

    .chat-input:focus { border-color: var(--teal); }

    .send-btn {
      width: 42px; height: 42px;
      background: var(--teal);
      border: none; border-radius: 50%;
      cursor: pointer;
      display: flex; align-items: center; justify-content: center;
      flex-shrink: 0; transition: opacity .2s;
      box-shadow: 0 2px 10px rgba(10,147,150,.35);
    }

    .send-btn:hover { opacity: .9; }
    .send-btn svg { width: 18px; height: 18px; stroke: white; }

    /* ════════════════════════════════════════
       PHONE MODAL
    ════════════════════════════════════════ */
    .modal-overlay {
      display: none; position: fixed; inset: 0;
      background: rgba(0,0,0,.45); z-index: 200;
      align-items: flex-end; justify-content: center;
    }

    .modal-overlay.open { display: flex; animation: fadeIn .2s ease; }

    .modal {
      background: var(--white);
      border-radius: 24px 24px 0 0;
      padding: 28px 24px 40px;
      width: 100%; max-width: 100%;
      animation: slideUp .25s ease;
    }

    .modal-handle {
      width: 40px; height: 4px;
      background: var(--border); border-radius: 2px;
      margin: 0 auto 24px;
    }

    .modal-title { font-size: 20px; font-weight: 800; color: var(--text); margin-bottom: 6px; }
    .modal-sub { font-size: 13px; color: var(--text-2); margin-bottom: 22px; line-height: 1.5; }

    .phone-input {
      width: 100%; padding: 14px 16px;
      border: 1.5px solid var(--border);
      border-radius: var(--radius); margin-bottom: 14px;
      font-family: 'Inter', sans-serif; font-size: 16px;
      outline: none; transition: border-color .2s;
    }

    .phone-input:focus { border-color: var(--teal); }

    /* Groups a fixed, non-editable "+1" prefix with the phone number field so
       the country code isn't something the user types (or can type wrong) —
       the input itself only ever holds the 10 local digits. */
    .phone-input-group {
      display: flex; align-items: center;
      border: 1.5px solid var(--border);
      border-radius: var(--radius); margin-bottom: 14px;
      overflow: hidden; transition: border-color .2s;
    }
    .phone-input-group:focus-within { border-color: var(--teal); }
    .phone-input-prefix {
      padding: 14px 10px 14px 16px;
      font-family: 'Inter', sans-serif; font-size: 16px; font-weight: 600;
      color: var(--text-2); background: var(--surface);
      border-right: 1.5px solid var(--border);
      flex-shrink: 0;
    }
    .phone-input-group .phone-input {
      flex: 1; min-width: 0; border: none; margin-bottom: 0;
      padding: 14px 16px 14px 10px;
    }

    .modal-btn {
      width: 100%; padding: 15px;
      background: var(--navy);
      color: white; border: none;
      border-radius: var(--radius);
      font-family: 'Inter', sans-serif;
      font-size: 15px; font-weight: 700;
      cursor: pointer; transition: opacity .2s;
      box-shadow: 0 4px 16px rgba(10,147,150,.3);
    }

    .modal-btn:hover { opacity: .9; }
    .modal-privacy { font-size: 11px; color: var(--text-3); text-align: center; margin-top: 12px; }

    /* ════════════════════════════════════════
       DESKTOP TOP HEADER (hidden on mobile)
    ════════════════════════════════════════ */
    .desktop-header { display: none; }
    .desktop-subnav { display: none; }

    /* Desktop-only home sections (hero explainer + category showcase) and the
       product-page breadcrumb — hidden on mobile, shown inside the
       min-width:768px query below. */
    .lb-hero, .lb-cat-showcase { display: none; }
    .pd-desktop-breadcrumb {
      display: none;
      align-items: center; gap: 6px;
      font-size: 12.5px; color: var(--text-3);
      padding: 0 4px;
    }
    .pd-desktop-breadcrumb a { color: var(--teal-dark); font-weight: 600; cursor: pointer; }

    /* Building-selection hero (desktop redesign) — .s1-hero-inner/.s1-hero-copy
       are neutral wrappers with no base layout rules so mobile is unaffected;
       .s1-hero-visual is a new decorative card, hidden on mobile like the
       other desktop-only sections above. */
    .s1-hero-visual { display: none; }
    /* Desktop-only back button for the "How it works" panel (matches the
       Event activity / Cart panel back-btn) — mobile keeps just the ×
       close button on its bottom sheet. */
    .how-back-btn { display: none; }
    .pd-desktop-breadcrumb a:hover { text-decoration: underline; }

    /* min-height:501px is the counterpart to the portrait lock at the top of
       this file: a phone held sideways is ~844x390, which WOULD satisfy
       min-width:768px and flip the whole app into the desktop layout while
       it is being counter-rotated into a 390px-wide box. Requiring real
       vertical room keeps desktop styling for actual desktops/tablets only.
       Keep this threshold in sync with LB_DESKTOP_MIN_HEIGHT in lobbybuy.js. */
    @media (min-width: 768px) and (min-height: 501px) {
      /* Real page scroll instead of a boxed-in inner scroll panel: html/body
         grow with content and the browser's own (full-height) scrollbar
         does the scrolling, matching Amazon/professional desktop sites.
         The header + subnav are pinned via position:sticky below instead
         of just sitting outside a fixed-height flex column. */
      /* overflow-x uses "clip" rather than "hidden" everywhere below: pairing
         a non-visible overflow-x with overflow-y:visible silently upgrades
         overflow-y to auto too (CSS overflow spec), which would turn each of
         these into its own scroll container and break position:sticky for
         the header/subnav (they'd stick to the wrong ancestor and just
         scroll away). "clip" is exempt from that pairing rule, so it clips
         the off-screen mobile drawer horizontally without creating a
         scrolling box. */
      html, body {
        background: #f3f4f6;
        height: auto;
        min-height: 100%;
        overflow-x: clip;
        overflow-y: visible;
      }

      .phone-shell {
        flex-direction: column;
        height: auto;
        min-height: 100vh;
        width: 100vw;
        background: #f3f4f6;
        overflow-x: clip;
        overflow-y: visible;
      }

      /* While a side panel (Chat/Cart/Status/Orders), the drawer, or How it
         works is open over the page, freeze the main page's own scrollbar
         so scrolling only happens inside the open panel. Toggled by
         _updateBodyScrollLock() in lobbybuy.js; class-selector specificity
         beats the plain html/body rule above without needing !important. */
      html.lb-scroll-locked, html.lb-scroll-locked body {
        overflow-y: hidden;
      }

      /* ── Top header bar (Amazon-style) ── */
      .desktop-header {
        display: flex;
        align-items: center;
        background: var(--navy);
        padding: 0 24px;
        height: 60px;
        flex-shrink: 0;
        width: 100%;
        position: sticky;
        top: 0;
        z-index: 50;
      }

      .dh-logo {
        display: flex; align-items: center; gap: 8px;
        padding: 0 16px 0 0;
        border-right: 1px solid rgba(255,255,255,.15);
        margin-right: 16px;
        cursor: pointer;
        text-decoration: none;
        flex-shrink: 0;
      }
      /* Full horizontal lockup (icon + wordmark + tagline) in place of the old
         small icon + "Lobbybuy" text mark — same treatment as the select-building
         hero logo, sized up to read clearly in the 60px header. */
      .dh-logo-full { height: 36px; width: auto; display: block; }

      .dh-location {
        display: flex; align-items: center; gap: 6px;
        padding: 6px 12px;
        border: 1.5px solid transparent;
        border-radius: 6px;
        cursor: pointer;
        flex-shrink: 0;
        transition: border-color .15s;
      }
      .dh-location:hover { border-color: white; }
      .dh-location-icon { color: #52E8C2; }
      .dh-location-icon svg { width: 16px; height: 16px; stroke: #52E8C2; }
      .dh-location-text { display: flex; flex-direction: column; }
      .dh-location-label { font-size: 11px; color: rgba(255,255,255,.65); line-height: 1; }
      .dh-location-name { font-size: 13px; font-weight: 700; color: white; line-height: 1.3; }

      .dh-search {
        flex: 1;
        display: flex;
        align-items: center;
        margin: 0 16px;
        background: white;
        border-radius: 6px;
        overflow: hidden;
        height: 38px;
      }
      .dh-search input {
        flex: 1; border: none; outline: none;
        padding: 0 14px;
        font-family: 'Inter', sans-serif;
        font-size: 14px; color: var(--text);
      }
      .dh-search-btn {
        width: 42px; height: 38px;
        background: var(--teal);
        border: none; cursor: pointer;
        display: flex; align-items: center; justify-content: center;
        transition: background .15s;
        flex-shrink: 0;
      }
      .dh-search-btn:hover { background: var(--teal-dark); }
      .dh-search-btn svg { width: 18px; height: 18px; stroke: white; }

      .dh-actions {
        display: flex; align-items: center; gap: 4px;
        margin-left: 8px;
        flex-shrink: 0;
      }
      .dh-action-btn {
        display: flex; align-items: center; gap: 6px;
        padding: 6px 10px;
        border: 1.5px solid transparent;
        border-radius: 6px;
        cursor: pointer;
        transition: border-color .15s;
        color: white;
        text-decoration: none;
        position: relative;
      }
      .dh-action-btn:hover { border-color: white; }
      .dh-action-btn svg { width: 18px; height: 18px; stroke: white; }
      /* Account is icon-only (no label) — a bit more padding and a bigger
         icon so it doesn't look small/lost next to Chat/Cart's two-line
         buttons. */
      .dh-menu-btn { padding: 8px 12px; }
      .dh-menu-btn svg { width: 24px; height: 24px; }
      .dh-action-text { display: flex; flex-direction: column; }
      .dh-action-label { font-size: 11px; color: rgba(255,255,255,.65); line-height: 1; }
      .dh-action-name { font-size: 13px; font-weight: 700; color: white; line-height: 1.3; }
      .dh-cart-count {
        font-size: 18px; font-weight: 700; color: #52E8C2;
        min-width: 18px; text-align: center;
      }

      /* ── Secondary nav strip ── */
      .desktop-subnav {
        display: flex;
        align-items: center;
        background: var(--harbor);
        padding: 0 24px;
        height: 38px;
        flex-shrink: 0;
        width: 100%;
        overflow-x: auto;
        scrollbar-width: none;
        position: sticky;
        top: 60px; /* sits directly under the sticky .desktop-header */
        z-index: 45;
      }
      .desktop-subnav::-webkit-scrollbar { display: none; }
      .dsn-item {
        display: flex; align-items: center;
        padding: 0 12px;
        height: 38px;
        font-size: 13px; font-weight: 500; color: rgba(255,255,255,.85);
        cursor: pointer; white-space: nowrap;
        border: 1.5px solid transparent;
        transition: all .15s;
        border-radius: 4px;
      }
      .dsn-item:hover { border-color: white; color: white; }
      .dsn-item.active { color: white; font-weight: 700; border-color: white; }

      /* #dsn-about ("About Us" ▾) — same pill as the other dsn-items, plus
         a chevron that flips when its dropdown (#about-dropdown) is open. */
      #dsn-about { gap: 4px; }
      #dsn-about .dsn-chevron { width: 10px; height: 10px; transition: transform .15s; }
      #dsn-about.open { border-color: white; color: white; }
      #dsn-about.open .dsn-chevron { transform: rotate(180deg); }

      /* Small round thumbnail in front of the label on the desktop sub-nav.
         The subnav sits on the teal header bar, so the ring is white-on-photo. */
      .dsn-cat-avatar {
        width: 22px; height: 22px; border-radius: 50%;
        overflow: hidden; flex-shrink: 0; margin-right: 7px;
        background: rgba(255, 255, 255, .18);
        box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .35);
        display: flex; align-items: center; justify-content: center;
        font-size: 12px; line-height: 1;
      }

      /* ── Main content area ── */
      .sidebar { display: none; }
      .main-content {
        flex: none;
        display: flex;
        flex-direction: column;
        overflow-x: clip;
        overflow-y: visible;
        min-width: 0;
        background: #f3f4f6;
      }


      /* Hide mobile-only elements */
      .bottom-nav { display: none !important; }
      .topbar { display: none !important; }

      /* #drawer/#drawer-overlay are position:absolute + height:100% inline
         in the HTML, sized against .phone-shell — fine on mobile where
         .phone-shell is a fixed 100vh box, but now that .phone-shell grows
         to full page content height on desktop (real page scroll), that
         100% would stretch the drawer to the whole page instead of just the
         viewport. !important is needed to beat those inline styles; "right"
         (which openDrawer/closeDrawer toggle) is left alone since it's
         still the same 280px-wide element. */
      #drawer-overlay { position: fixed !important; }
      #drawer { position: fixed !important; height: 100vh !important; }

      /* Screens: content flows naturally and the real page scrolls (see
         html/body/.phone-shell above) instead of each screen being its own
         fixed-height box with an inner scrollbar. #screen-chat, #screen-
         basket, #screen-status and #screen-orders are the deliberate
         exception — see the slide-in side-panel treatment below. */
      .screen { overflow-y: visible; overflow-x: clip; flex: none; background: #f3f4f6; }

      /* Chat, Cart, Event activity and My orders open as slide-in panels
         over whatever page is currently showing (see showScreen()'s desktop
         PANEL_SCREENS branch in lobbybuy.js), instead of replacing it like
         every other screen. Same visual language as the account #drawer,
         but animated with transform instead of the "right" offset: these
         screens stay display:flex at all times (!important beats the base
         .screen{display:none} — intentional here, unlike the bare-ID bug
         fixed earlier, because translateX(100%) + pointer-events:none keeps
         them fully off-screen and non-interactive until .active is added)
         so toggling .active can transition smoothly rather than snapping. */
      #panel-overlay {
        display: none;
        position: fixed;
        inset: 0;
        background: rgba(0,0,0,.4);
        z-index: 79;
      }
      #screen-chat, #screen-basket, #screen-status, #screen-orders,
      #screen-delivery, #screen-payment, #screen-confirm, #screen-profile {
        display: flex !important;
        flex-direction: column;
        position: fixed;
        top: 0; right: 0;
        width: 420px;
        max-width: 92vw;
        height: 100vh;
        z-index: 80;
        background: white;
        box-shadow: -4px 0 20px rgba(0,0,0,.18);
        border-radius: 0;
        margin: 0;
        overflow: hidden;
        transform: translateX(100%);
        transition: transform .28s ease;
        pointer-events: none;
        /* Kill the base .screen fadeIn. Its keyframes animate `transform`
           (translateY(8px) → translateY(0)), and an animation's value beats a
           normal declaration — so for the .25s it ran on page load it replaced
           the translateX(100%) above and parked these panels at x=0, fully
           on screen, before snapping back when the animation ended. That was
           the chat panel flashing on every refresh. The slide-in is driven by
           `transition` + .active here, so no entry animation is wanted. */
        animation: none;
      }
      #screen-chat.active, #screen-basket.active, #screen-status.active, #screen-orders.active,
      #screen-delivery.active, #screen-payment.active, #screen-confirm.active, #screen-profile.active {
        transform: translateX(0);
        pointer-events: auto;
      }
      #screen-chat .chat-messages { overflow-y: auto; }

      /* "Verify your email" during checkout.
         The OTP sheet is a full-width bottom sheet by default, which is right on
         mobile but wrong on desktop mid-checkout: the flow is running inside the
         420px right-hand panel, so a sheet spanning the whole window looks like
         it belongs to the page behind rather than to the checkout in progress.
         openOtpModal() adds .otp-in-panel only when a panel is actually open, so
         the same modal opened from the Contact screen keeps the default look. */
      #otp-modal.otp-in-panel {
        justify-content: flex-end;
        align-items: center;
        background: rgba(0,0,0,.28);   /* lighter — the panel already dims the page */
      }
      #otp-modal.otp-in-panel .modal {
        width: 420px;
        max-width: 92vw;
        margin-right: 0;
        border-radius: 20px 0 0 20px;
        padding: 28px 24px 32px;
        animation: fadeIn .18s ease;   /* slide-up reads oddly when it's not bottom-anchored */
        max-height: 100vh;
        overflow-y: auto;
      }
      /* The drag handle only makes sense on a bottom sheet. */
      #otp-modal.otp-in-panel .modal-handle { display: none; }
      /* No extra scroll rule needed for the checkout panels: screen-delivery,
         screen-payment and screen-confirm each already carry
         `flex:1; overflow-y:auto` inline on their body div, which is exactly
         what the fixed-height flex-column panel box wants. screen-delivery's
         last child is a flex-shrink:0 sticky footer holding the Continue
         button — don't make that scroll. */

      /* "How it works" — same right-to-left slide-in treatment as the Chat/
         Cart panels above, instead of the mobile bottom-sheet. #how-modal
         is the backdrop (already toggled via .open, already closes on a
         backdrop click — see openHowItWorks()/closeHowItWorks()); it stays
         rendered (display:flex !important) so the box's transform can
         transition, same reasoning as the chat/basket panels. */
      #how-modal {
        display: flex !important;
        justify-content: flex-end;
        align-items: stretch;
        background: transparent;
        pointer-events: none;
        transition: background .28s ease;
      }
      #how-modal.open {
        background: rgba(0,0,0,.4);
        pointer-events: auto;
      }
      #how-modal-box {
        width: 420px;
        max-width: 92vw;
        height: 100vh;
        max-height: 100vh;
        border-radius: 0;
        padding: 28px 28px 32px;
        box-shadow: -4px 0 20px rgba(0,0,0,.18);
        transform: translateX(100%);
        transition: transform .28s ease;
      }
      #how-modal.open #how-modal-box {
        transform: translateX(0);
      }
      /* Swap the × close button for the same back-btn used by the other
         panels, and give Chat/Event activity/Cart's back-btn the
         matching right-pointing arrow — mirrored via transform rather than
         a different SVG path, so mobile (which shares this exact markup)
         keeps its original left-pointing "back" chevron untouched. The
         arrow points right because that's the direction each panel
         physically slides back out to when closed. Account (#drawer) gets
         its own new back-btn below since it never had a close button. */
      .how-close-x { display: none; }
      .how-back-btn {
        display: flex; align-items: center; justify-content: center;
        background: var(--surface); border: none; border-radius: 10px;
        width: 34px; height: 34px; cursor: pointer; flex-shrink: 0;
      }
      .how-back-btn svg { width: 18px; height: 18px; stroke: var(--navy); }
      /* Title bar: match the navy/harbor gradient header used by the other
         panels (Chat/Cart/Event activity/Orders) instead of the plain
         white row the mobile bottom-sheet uses. Bled out to the box edges
         with negative margins since #how-modal-box keeps its 28px padding
         for the content below. */
      .how-topbar {
        margin: -28px -28px 20px !important;
        padding: 16px 20px;
        background: linear-gradient(135deg, var(--navy) 0%, var(--harbor) 100%);
      }
      .how-topbar-title { color: white !important; }
      /* The back-btn's base style is a light var(--surface) card meant for
         the plain white row it used to sit on — now that it sits on the
         gradient .how-topbar, it needs the same translucent-white treatment
         as the other panels' back buttons, or the white icon disappears
         against the light background. */
      .how-topbar .how-back-btn { background: rgba(255,255,255,.15); }

      /* Legal modal gets the exact same mobile-sheet → desktop slide-in-panel
         treatment as #how-modal just above — same reasoning, same rules,
         just targeting #legal-modal/#legal-modal-box. */
      #legal-modal {
        display: flex !important;
        justify-content: flex-end;
        align-items: stretch;
        background: transparent;
        pointer-events: none;
        transition: background .28s ease;
      }
      #legal-modal.open {
        background: rgba(0,0,0,.4);
        pointer-events: auto;
      }
      #legal-modal-box {
        width: 420px;
        max-width: 92vw;
        height: 100vh;
        max-height: 100vh;
        border-radius: 0;
        padding: 28px 28px 32px;
        box-shadow: -4px 0 20px rgba(0,0,0,.18);
        transform: translateX(100%);
        transition: transform .28s ease;
        display: flex;
        flex-direction: column;
      }
      #legal-modal.open #legal-modal-box {
        transform: translateX(0);
      }
      /* Drawer's back-btn sits on the dark navy/harbor gradient header
         instead of a white card, so it needs a white icon. */
      .drawer-back-btn svg, .drawer-back-btn svg path { stroke: white; }
      #screen-status .back-btn svg, #screen-basket .back-btn svg, #screen-chat .back-btn svg, #screen-orders .back-btn svg, #screen-profile .back-btn svg {
        transform: scaleX(-1);
      }
      .orders-back-btn { display: flex; }
      .profile-back-btn { display: flex; }

      /* Side panels (Cart/Chat/Event activity/Orders): the back button
         alone is enough — hide the auto-injected drawer-hamburger in each
         topbar (it duplicates the header's own menu trigger). For Chat this
         only hides the topbar hamburger; the separate Clear History/Privacy
         menu button in the chat input bar is untouched. Event activity
         also hides its "Chat →" shortcut button. */
      #screen-basket .chat-topbar .icon-btn,
      #screen-chat .chat-topbar .icon-btn,
      #screen-status .chat-topbar .icon-btn,
      #screen-status .chat-topbar .banner-btn,
      #screen-orders .chat-topbar .icon-btn,
      #screen-profile .chat-topbar .icon-btn { display: none; }

      /* Grid screen content */
      #screen-grid .banner { margin: 20px 24px 0; border-radius: 14px; min-height: 0; padding: 0; }
      #screen-grid .cats-wrap { display: none !important; }
      /* grid-cat-back is an ID in the markup, not a class — both rules
         below previously used ".grid-cat-back" and silently matched
         nothing. Fixed to "#grid-cat-back". */
      #screen-grid #grid-cat-back { padding: 14px 24px 4px !important; }
      /* The category back bar's cart/chat icons duplicate the main
         desktop-header's own cart/chat above — same reasoning as the
         chat-topbar hides at #1817 and the product-screen comment at
         #2188. Keep only the back arrow + category label on desktop. */
      #screen-grid #grid-cat-back .icon-btn { display: none; }
      #screen-grid .grid-wrap { padding: 16px 24px 24px; }
      .grid { grid-template-columns: repeat(3, 1fr); gap: 14px; }
      .pcard { background: white; }

      /* Desktop banner — flat single-row status strip (matches the approved
         concept: dot + status line, stat columns with dividers, a link on
         the right). flex-shrink:0 so it can't collapse the way .lb-hero did
         before that fix — same #screen-grid flex-column-taller-than-viewport
         situation applies here. */
      .banner-desktop {
        display: flex;
        flex-shrink: 0;
        align-items: center;
        width: auto;
        margin: 0;
        border-radius: 0;
        padding: 14px 28px;
        gap: 22px;
        background: var(--teal-dark);
        color: white;
        box-shadow: none;
      }
      .bd-dot {
        width: 7px; height: 7px; border-radius: 99px; flex-shrink: 0;
        background: var(--accent); box-shadow: 0 0 0 4px rgba(82,232,194,.25);
      }
      .bd-status {
        flex: 1; min-width: 0;
        font-size: 13px; color: rgba(255,255,255,.85);
      }
      .bd-status b { color: white; }
      #grid-banner-desktop .banner-pill {
        display: inline; background: none; padding: 0; margin: 0;
        font-size: 13px; font-weight: 800; color: white;
      }
      .banner-desktop-stats {
        display: flex;
        flex-shrink: 0;
      }
      .banner-stat {
        padding: 0 20px;
        display: flex; flex-direction: column; align-items: center; justify-content: center;
        border-left: 1px solid rgba(255,255,255,.15);
        gap: 2px;
      }
      .banner-stat:first-child { border-left: none; }
      .banner-stat-value { font-size: 17px; font-weight: 800; color: white; line-height: 1; }
      .banner-stat-label { font-size: 10px; color: rgba(255,255,255,.6); font-weight: 500; text-align: center; line-height: 1.4; }
      .bd-link {
        font-size: 12.5px; font-weight: 700; color: var(--accent);
        cursor: pointer; flex-shrink: 0; white-space: nowrap;
      }
      .bd-link:hover { text-decoration: underline; }

      /* Basket/product action bar: in-flow on desktop, not fixed */
      .basket-checkout-bar {
        position: static;
        padding: 16px 24px 24px;
        border-top: 1px solid var(--border);
        background: white;
        flex-shrink: 0;
      }
      .mobile-only-spacer { display: none; }

      /* Other screens: centered column (screen-product gets its own wide
         Amazon-style layout below instead of this centered card). These
         grow naturally with the real page scroll — the slide-in panels
         (chat, basket, status, orders, and the whole checkout flow) are the
         exceptions handled above.

         screen-delivery / screen-payment / screen-confirm USED to be listed
         here. They must NOT be: this block comes later in the file, so at equal
         ID specificity its width:100% / max-width:760px / margin:0 auto would
         beat the panel rule's width:420px and blow the panel out to full width. */
      #screen-categories {
        max-width: 760px;
        margin: 0 auto;
        width: 100%;
        background: white;
        box-shadow: var(--shadow);
        border-radius: 0;
      }

      /* Building screen — full width so the hero can go edge-to-edge.
         Desktop redesign 2026-07-22: matches the warehouse-direct concept
         (light mint theme, same palette as .lb-hero). Same DOM + JS logic —
         only styling changes; mobile rules above are untouched. */
      #screen-building {
        max-width: none;
        margin: 0;
        width: 100%;
        --lbh-deep:#073B39; --lbh-teal:#0A4A47; --lbh-mint:#3FE3C1;
        --lbh-ink:#0B2E2B; --lbh-em:#0F9E7E; --lbh-tint:#EAF7F3;
        --lbh-line:#DCEBE7; --lbh-muted:#6A8480;
        background: #F4FBF9;
      }
      #screen-building .s1-hero {
        padding: 56px 40px 4px;
        background: #F4FBF9;                /* replaces mobile navy gradient */
      }
      #screen-building .s1-hero::before { display: none; }   /* mobile deco circles */
      #screen-building .s1-hero::after {
        top: auto; bottom: auto; left: auto; right: auto;    /* reset mobile circle */
        inset: 0; width: auto; height: auto; border-radius: 0;
        background: radial-gradient(620px 320px at 82% 12%, rgba(63,227,193,.20), transparent 70%);
        pointer-events: none;
      }
      #screen-building .s1-hero-inner {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 48px;
        max-width: 1100px;
        margin: 0 auto;
        position: relative; z-index: 1;
      }
      #screen-building .s1-hero-copy {
        display: flex;
        flex-direction: column;
        flex: 1;
        max-width: 520px;
      }
      #screen-building .logo { margin-bottom: 24px; }
      #screen-building .s1-logo-full { height: 57px; }
      #screen-building .s1-logo-full-mobile { display: none; }
      #screen-building .s1-logo-full-desktop { display: block; }
      #screen-building .s1-help-link {
        margin: 10px auto 0;
        color: var(--lbh-teal);
        background-image: linear-gradient(var(--lbh-em), var(--lbh-em));
      }
      #screen-building .s1-help-link:hover { color: var(--lbh-em); }
      /* .s1-sub keeps its original text/DOM position (mobile untouched) but
         is restyled into a pill badge and moved above the title visually
         via flex order — same real element, no duplicated copy. */
      #screen-building .s1-sub {
        order: -1;
        align-self: flex-start;
        display: inline-flex;
        align-items: center;
        background: var(--lbh-tint);
        color: var(--lbh-teal);
        border: 1px solid var(--lbh-line);
        font-size: 12px;
        font-weight: 700;
        padding: 6px 14px;
        border-radius: 99px;
        margin-bottom: 16px;
      }
      #screen-building .s1-title {
        font-size: 40px;
        line-height: 1.12;
        letter-spacing: -.7px;
        margin-bottom: 0;
        color: var(--lbh-ink);
      }
      /* Visual: same inline SVG scene as the homepage hero (.lb-hero-svg);
         the mobile floating cards are hidden and replaced by the SVG.
         Previously a flat background-image (lobbybuy-hero-warehouse.png,
         kept on disk) — swapped 2026-08-08 to match the main-page hero. */
      #screen-building .s1-hero-visual {
        display: block;
        position: relative;
        flex-shrink: 0;
        width: 400px;
        height: 350px;
        filter: drop-shadow(0 20px 34px rgba(7,59,57,.18));
      }
      #screen-building .s1-hero-visual .s1-hv-svg { display: block; width: 100%; height: 100%; }
      #screen-building .s1-hero-visual .s1-hv-svg > g { filter: drop-shadow(0 18px 30px rgba(7,59,57,.20)); }
      #screen-building .s1-hv-card { display: none; }
      /* desktop screen-1 already has its own hero visual — hide the mobile explainer */
      #screen-building .s1-concept { display: none; }

      /* Search area — stays in its original DOM position (sibling of .s1-hero,
         no JS reparenting) but is pulled up visually right under the title by
         sharing the exact same centering box as .s1-hero-inner (max-width:1100px
         + 40px side padding), so its left edge lines up with the title above it. */
      #screen-building .s1-body {
        overflow-y: visible;
        flex: none;
        max-width: 1100px;
        margin: 0 auto;
        width: 100%;
        padding: 8px 40px 56px;
        background: transparent;
      }
      /* Desktop already says this via the floating .s1-hv-float card. */
      #screen-building .s1-search-label { display: none; }
      #screen-building .search-wrap,
      #screen-building #postal-results,
      #screen-building .buildings-list {
        max-width: 460px;
      }
      #screen-building .search-input {
        padding: 16px 16px 16px 48px;
        font-size: 15px;
        border: 1.5px solid var(--lbh-line);
        border-radius: 14px;
        box-shadow: 0 10px 30px -12px rgba(7,59,57,.16);
      }
      #screen-building .search-input:focus {
        border-color: var(--lbh-em);
        box-shadow: 0 0 0 3px rgba(15,158,126,.14);
      }
      #screen-building .search-icon { left: 17px; color: var(--lbh-muted); }

      /* ════════════════════════════════════════
         DESKTOP HOME — explainer hero (FoodsUp-style)
         + category showcase. Hidden on mobile by default
         (see base .lb-hero / .lb-cat-showcase rules above screen system).
      ════════════════════════════════════════ */
      /* concept palette (Lobbybuy — Warehouse-Direct Hero) */
      .lb-hero {
        --lbh-deep:#073B39; --lbh-teal:#0A4A47; --lbh-mint:#3FE3C1; --lbh-mint-btn:#5CEBCE;
        --lbh-ink:#0B2E2B; --lbh-em:#0F9E7E; --lbh-tint:#EAF7F3; --lbh-line:#DCEBE7; --lbh-muted:#6A8480;
        display: block;
        flex-shrink: 0;   /* #screen-grid is a flex column taller than the viewport;
                             without this, overflow:hidden below disables this item's
                             automatic min-height and the flex-shrink algorithm collapses
                             it to 0 instead of letting the column scroll. */
        background: #F4FBF9;
        border-radius: 0;
        margin: 0;
        position: relative;
        overflow: hidden;
      }
      .lb-hero::after {
        content: ''; position: absolute; inset: 0; pointer-events: none;
        background: radial-gradient(620px 320px at 85% 18%, rgba(63,227,193,.20), transparent 70%);
      }
      .lb-hero-inner {
        display: flex; align-items: center; gap: 40px;
        padding: 44px 40px 40px; position: relative; z-index: 1;
      }
      .lb-hero-copy { flex: 1; max-width: 560px; }
      .lb-hero-pill {
        display: inline-flex; align-items: center; gap: 7px;
        background: var(--lbh-tint); color: var(--lbh-teal); border: 1px solid var(--lbh-line);
        font-size: 12px; font-weight: 700; padding: 6px 14px; border-radius: 99px;
      }
      .lb-hero-title {
        font-size: 38px; font-weight: 800; color: var(--lbh-ink); line-height: 1.1;
        margin-top: 16px; letter-spacing: -.7px;
      }
      .lb-hero-title em { color: var(--lbh-em); font-style: normal; }
      .lb-hero-sub {
        font-size: 14.5px; color: var(--lbh-muted); line-height: 1.62;
        margin-top: 14px; max-width: 470px;
      }
      .lb-hero-badges { display: flex; gap: 20px; margin-top: 22px; flex-wrap: wrap; }
      .lb-hero-badge { display: flex; align-items: center; gap: 9px; }
      .lb-hero-badge-icon {
        width: 32px; height: 32px; border-radius: 9px; background: var(--lbh-tint);
        display: flex; align-items: center; justify-content: center; flex-shrink: 0; font-size: 15px;
      }
      .lb-hero-badge-text { font-size: 12px; font-weight: 700; color: var(--lbh-ink); line-height: 1.3; }
      .lb-hero-cta-row { display: flex; align-items: center; gap: 20px; margin-top: 26px; }
      .lb-hero-btn {
        display: inline-flex; align-items: center; gap: 8px;
        background: var(--lbh-teal); color: #fff; border: none;
        font-family: 'Inter', sans-serif; font-size: 14px; font-weight: 800;
        padding: 14px 26px; border-radius: 12px; cursor: pointer;
        transition: transform .15s, box-shadow .15s;
        box-shadow: 0 12px 26px -10px rgba(10,74,71,.5);
      }
      .lb-hero-btn:hover { transform: translateY(-1px); box-shadow: 0 14px 30px -10px rgba(10,74,71,.6); }
      .lb-hero-link {
        font-size: 13.5px; font-weight: 700; color: var(--lbh-ink);
        cursor: pointer; border-bottom: 1px solid var(--lbh-line); padding-bottom: 2px;
      }
      .lb-hero-link:hover { color: var(--lbh-em); }

      /* warehouse-direct hero illustration (from concept deck) */
      .lb-hero-visual { flex-shrink: 0; width: 480px; max-width: 46%; position: relative; }
      .lb-hero-visual img { display: block; width: 100%; height: auto;
        filter: drop-shadow(0 24px 40px rgba(7,59,57,.20)); }
      /* SVG version: shadow goes on the structure groups, NOT the whole <svg>,
         otherwise the brand lockup <image> inside it gets ghosted too. */
      .lb-hero-visual .lb-hero-svg { display: block; width: 100%; height: auto; }
      .lb-hero-visual .lb-hero-svg > g { filter: drop-shadow(0 18px 30px rgba(7,59,57,.20)); }

      .lb-cat-showcase { display: block; margin: 28px 24px 0; }
      .lb-cat-showcase-head { margin-bottom: 14px; }
      .lb-cat-showcase-eyebrow {
        font-size: 11px; font-weight: 700; color: var(--teal); text-transform: uppercase; letter-spacing: .6px;
      }
      .lb-cat-showcase-title { font-size: 19px; font-weight: 800; color: var(--text); margin-top: 3px; }
      .lb-cat-scroll-wrap { position: relative; }
      .lb-cat-arrow {
        position: absolute; top: 50%; transform: translateY(-50%);
        width: 36px; height: 36px; border-radius: 99px; flex-shrink: 0;
        background: white; border: 1px solid var(--border); box-shadow: var(--shadow);
        display: flex; align-items: center; justify-content: center;
        cursor: pointer; z-index: 5; transition: box-shadow .15s, opacity .15s, visibility .15s;
      }
      .lb-cat-arrow:hover { box-shadow: var(--shadow-lg); }
      .lb-cat-arrow svg { width: 18px; height: 18px; color: var(--text); }
      .lb-cat-arrow-left { left: -18px; }
      .lb-cat-arrow-right { right: -18px; }
      .lb-cat-arrow.disabled { opacity: 0; visibility: hidden; pointer-events: none; }
      .lb-cat-showcase-grid {
        display: flex; gap: 12px; overflow-x: auto; padding-bottom: 4px;
        scrollbar-width: none; -webkit-overflow-scrolling: touch;
        scroll-behavior: smooth;
      }
      .lb-cat-showcase-grid::-webkit-scrollbar { display: none; }
      .lb-cat-card {
        flex: 0 0 130px;
        background: white; border: 1px solid var(--border); border-radius: 12px;
        padding: 16px 10px; text-align: center; cursor: pointer;
        transition: box-shadow .15s, transform .15s, border-color .15s;
      }
      .lb-cat-card:hover { box-shadow: var(--shadow); transform: translateY(-2px); border-color: var(--teal-light); }
      .lb-cat-card-icon {
        width: 46px; height: 46px; border-radius: 12px; background: var(--teal-pale);
        display: flex; align-items: center; justify-content: center; font-size: 21px; margin: 0 auto 8px;
      }
      /* Photo variant: a round 60px avatar instead of the 46px rounded square,
         so the showcase matches the circular treatment used everywhere else. */
      .lb-cat-card-icon.has-photo {
        width: 60px; height: 60px; border-radius: 50%;
        overflow: hidden; margin: 0 auto 10px;
        box-shadow: 0 1px 4px rgba(0, 0, 0, .1), inset 0 0 0 1px rgba(0, 0, 0, .05);
        transition: box-shadow .15s;
      }
      .lb-cat-card:hover .lb-cat-card-icon.has-photo { box-shadow: 0 4px 12px rgba(0, 0, 0, .16); }
      .lb-cat-card-name { font-size: 12px; font-weight: 700; color: var(--text); }

      /* ════════════════════════════════════════
         DESKTOP PRODUCT DETAIL — Amazon-style 3-column layout.
         #pd-scroll is unwrapped (display:contents) so its 4 children
         (gallery / info / tier / more) become direct grid items of
         #screen-product alongside chat-topbar and the Add to Basket bar —
         no element is duplicated or moved, only re-positioned. Mobile is
         completely untouched (this whole block lives inside the
         min-width:768px query).
      ════════════════════════════════════════ */
      #screen-product.active {
        display: grid;
        grid-template-columns: 380px 1fr;
        /* Buy box (grid-area: cta) sits in normal flow right under the tier
           progress bar, in the same column as info/tier — not a sticky
           right-hand rail. "gallery" spans all three of those rows so it
           stays put at the top of the (now taller) middle column while info
           → tier → cta stack underneath it. "more" (related products) drops
           out to its own full-width row below everything else. */
        grid-template-areas:
          "crumb    crumb"
          "gallery  info"
          "gallery  tier"
          "gallery  cta"
          "more     more"
          "footer   footer";
        gap: 22px 28px;
        align-items: start;
        max-width: 1320px;
        margin: 0 auto;
        width: 100%;
        padding: 24px 24px 48px;
        background: transparent;
        box-shadow: none;
      }
      /* The mobile chat-topbar (back arrow / postal code / cart-chat-menu
         icons) duplicates the main desktop-header + breadcrumb above it —
         hidden on desktop, not just repositioned. */
      #screen-product .chat-topbar { display: none; }
      #screen-product .pd-desktop-breadcrumb { grid-area: crumb; }
      #pd-scroll { display: contents; }

      /* Desktop: footer expands from a stacked single column into a
         3-column row (brand / explore / support), matching the layout
         used by professional storefront footers. Applies to all screens;
         screen-product additionally needs it slotted into its grid. */
      .lb-footer { padding: 40px 40px 28px; }
      .lb-footer-main { flex-direction: row; gap: 48px; text-align: left; }
      .lb-footer-brand { flex: 1.6; }
      .lb-footer-col:not(.lb-footer-brand) { flex: 1; }

      #screen-product .lb-footer { grid-area: footer; padding-bottom: 24px; }

      /* ── Gallery ─────────────────────────────────────────────────────
         White (not grey) so the product photo — nearly always shot on
         white — reads as one clean plate instead of a floating tile. */
      #screen-product .pd-desktop-gallery {
        grid-area: gallery !important;
        height: 470px !important; font-size: 130px !important;
        background: #fff !important;
        padding: 30px !important;
        /* the !important border shorthand overrides the element's inline
           border-bottom (all four sides, same importance) */
        border: 1px solid var(--border) !important;
        border-radius: var(--radius) !important; align-self: start;
        box-shadow: var(--shadow-sm);
      }
      #screen-product .pd-desktop-gallery img { transition: transform .25s ease; }
      #screen-product .pd-desktop-gallery:hover img { transform: scale(1.04); }

      /* ── Title / price card ──────────────────────────────────────── */
      #screen-product .pd-desktop-info {
        grid-area: info; border: 1px solid var(--border) !important; border-radius: var(--radius);
        align-self: start; padding: 22px 24px !important; box-shadow: var(--shadow-sm);
      }
      #screen-product .pd-brand { font-size: 11.5px; letter-spacing: .9px; color: var(--teal-dark); }
      #screen-product .pd-title {
        font-size: 25px; line-height: 1.25; margin-top: 7px; letter-spacing: -.3px;
      }
      #screen-product .pd-price-block {
        margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--border);
        display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
      }
      #screen-product .pd-price { font-size: 34px; letter-spacing: -.8px; }
      #screen-product .pd-price-note {
        display: block; font-size: 12.5px; font-weight: 600; color: var(--text-3);
      }

      /* ── Group-buy card ──────────────────────────────────────────── */
      #screen-product .pd-desktop-tier {
        grid-area: tier; margin-top: 0 !important; border: 1px solid var(--border) !important;
        border-radius: var(--radius); align-self: start;
        padding: 20px 24px 22px !important; box-shadow: var(--shadow-sm);
      }
      #screen-product .pd-sec-h { font-size: 15px; letter-spacing: -.2px; margin-bottom: 10px; }
      #screen-product .pd-tier-msg { font-size: 14px; margin-bottom: 0; }
      /* The meter gets its own tinted panel so it reads as a live status
         module rather than a stray hairline in a sea of white. */
      #screen-product #pd-pbar-wrap {
        margin-top: 16px;
        background: var(--teal-pale);
        border: 1px solid #D6EBE9;
        border-radius: var(--radius-sm);
        padding: 16px 18px 14px;
      }
      #screen-product #pd-pbar-wrap .pcard-pbar-row { gap: 14px; }
      #screen-product #pd-pbar-wrap .pcard-pbar-track { height: 8px; background: #FFF; box-shadow: inset 0 0 0 1px #D6EBE9; }
      #screen-product #pd-pbar-wrap .pcard-pbar-fill  { height: 8px; }
      #screen-product #pd-pbar-wrap .pcard-pbar-thumb { width: 18px; height: 18px; border-radius: 3px; }
      #screen-product #pd-pbar-wrap .pcard-pbar-goal  { font-size: 19px; color: #9FB3B2; }
      #screen-product #pd-pbar-label {
        text-align: left; font-size: 13.5px !important; margin-top: 12px !important;
      }

      /* ── Details + related, full width below ─────────────────────── */
      #screen-product .pd-desktop-more {
        grid-area: more; border: 1px solid var(--border) !important; border-radius: var(--radius);
        padding: 4px 26px 26px !important; box-shadow: var(--shadow-sm);
      }
      #screen-product .pd-block-h {
        font-size: 16px; font-weight: 700; color: var(--text);
        text-transform: none; letter-spacing: -.2px; margin-bottom: 12px;
      }
      /* Vendor description HTML arrives as a wall of bolded fragments —
         give it a real reading measure and a calm type hierarchy. */
      #screen-product #pd-description {
        font-size: 14.5px; line-height: 1.75; color: var(--text-2); max-width: 78ch;
      }
      #screen-product #pd-description p { margin: 0 0 12px; }
      #screen-product #pd-description p:last-child { margin-bottom: 0; }
      #screen-product #pd-description b,
      #screen-product #pd-description strong { color: var(--text); font-weight: 700; }
      #screen-product #pd-description h1, #screen-product #pd-description h2,
      #screen-product #pd-description h3, #screen-product #pd-description h4,
      #screen-product #pd-description h5, #screen-product #pd-description h6 {
        font-size: 13.5px; font-weight: 700; color: var(--text);
        margin: 18px 0 8px; letter-spacing: -.1px;
      }
      #screen-product #pd-description ul,
      #screen-product #pd-description ol { margin: 0 0 12px; padding-left: 20px; }
      #screen-product #pd-description li { margin-bottom: 6px; }
      #screen-product #pd-description a { color: var(--teal-dark); font-weight: 600; }
      #screen-product #pd-description table { border-collapse: collapse; margin: 8px 0 14px; }
      #screen-product #pd-description td, #screen-product #pd-description th {
        border: 1px solid var(--border); padding: 7px 10px; font-size: 13.5px; text-align: left;
      }
      #screen-product #pd-description-wrap,
      #screen-product #pd-related-wrap { margin-top: 22px !important; padding-top: 20px !important; }
      #screen-product .pd-related-head { margin-bottom: 14px; }
      #screen-product #pd-related-seeall { font-size: 13px !important; }

      /* Related products: a real grid on desktop, not a phone-sized
         horizontal scroller. */
      #screen-product #pd-related-row {
        display: grid !important;
        grid-template-columns: repeat(auto-fill, minmax(178px, 1fr));
        gap: 16px !important;
        overflow: visible !important;
        padding-bottom: 0 !important;
      }
      #screen-product .pd-rel-card {
        flex: none;
        transition: border-color .15s, box-shadow .15s, transform .15s;
      }
      #screen-product .pd-rel-card:hover {
        border-color: var(--teal);
        box-shadow: 0 6px 18px rgba(15, 138, 131, .14);
        transform: translateY(-2px);
      }
      #screen-product .pd-rel-media { height: 168px; background: #fff; padding: 14px; }
      #screen-product .pd-rel-body { padding: 12px 14px 14px; border-top: 1px solid var(--border); }
      #screen-product .pd-rel-name { font-size: 13.5px; height: 35px; }
      #screen-product .pd-rel-price { font-size: 16px; margin-top: 7px; }

      /* ── Buy box ─────────────────────────────────────────────────── */
      #screen-product .basket-checkout-bar {
        grid-area: cta;
        /* Normal flow, not sticky — scrolls with the rest of the page like
           everything else in this column instead of pinning to the viewport. */
        position: static !important; align-self: start;
        /* the !important border shorthand overrides the desktop
           .basket-checkout-bar border-top above (all four sides) */
        border: 1px solid var(--border) !important;
        border-radius: var(--radius); background: white; box-shadow: var(--shadow);
        padding: 20px !important;
      }
      #screen-product .basket-checkout-bar .pd-buybox-extra { display: block; }
      #screen-product .pd-buybox-top { margin-bottom: 16px; }
      #screen-product .pd-buybox-price {
        font-size: 26px; font-weight: 800; color: var(--navy); letter-spacing: -.6px;
      }
      #screen-product .pd-buybox-sub {
        font-size: 12.5px; color: var(--text-3); line-height: 1.5; margin-top: 4px;
      }
      /* Stack the stepper above a full-width CTA — a 300px rail has no room
         for them side by side without squashing the button label. */
      #screen-product .pd-buybox-row { flex-direction: column; align-items: stretch; gap: 12px; }
      #screen-product .pd-buybox-row > div:first-child { justify-content: space-between; }
      #screen-product .pd-buybox-row > div:first-child > button { flex: 1; }
      #screen-product #pd-add-btn {
        padding: 15px !important; font-size: 15.5px !important;
        box-shadow: 0 4px 14px rgba(15, 138, 131, .28);
        transition: filter .15s, box-shadow .15s, transform .12s;
      }
      #screen-product #pd-add-btn:hover:not(:disabled) {
        filter: brightness(1.06); box-shadow: 0 6px 18px rgba(15, 138, 131, .34);
      }
      #screen-product #pd-add-btn:active:not(:disabled) { transform: translateY(1px); }
      #screen-product .pd-buybox-trust {
        list-style: none; margin: 16px 0 0; padding: 14px 0 0;
        border-top: 1px solid var(--border);
        display: flex; flex-direction: column; gap: 9px;
      }
      #screen-product .pd-buybox-trust li {
        position: relative; padding-left: 22px;
        font-size: 12.5px; line-height: 1.45; color: var(--text-2);
      }
      #screen-product .pd-buybox-trust li::before {
        content: '✓'; position: absolute; left: 0; top: -1px;
        color: var(--teal); font-weight: 800; font-size: 13px;
      }

      /* Three columns once there's room for a gallery, a details column and
         a buy rail side by side; below this the layout keeps the original
         two-column stack defined above. */
      @media (min-width: 1180px) {
        #screen-product.active {
          grid-template-columns: minmax(360px, 430px) minmax(0, 1fr) 308px;
          grid-template-areas:
            "crumb    crumb  crumb"
            "gallery  info   cta"
            "gallery  tier   cta"
            "more     more   more"
            "footer   footer footer";
        }
      }

      /* Desktop-only breadcrumb, hidden on mobile via the base rule above */
      .pd-desktop-breadcrumb {
        display: flex;
        padding: 2px 4px 0;
      }
      .pd-desktop-breadcrumb span { color: var(--text-3); }

      /* ════════════════════════════════════════
         DESKTOP CONTACT US — two-column layout: form on the left, a sticky
         support rail on the right. Same DOM as mobile; only the wrap becomes
         a grid and the aside detaches into its own column.

         ⚠ EVERY selector here is prefixed with #screen-contact ON PURPOSE.
         The mobile .lb-contact-* rules live at the BOTTOM of this file, i.e.
         AFTER this media query. @media adds no specificity, so with plain
         class selectors the later mobile block wins every property both
         declare — which silently half-applied this layout: `display:grid` and
         `grid-template-columns` (declared only here) took effect while
         `max-width` and `padding` were dragged back to the mobile values,
         producing a 680px-wide desktop grid. The id prefix (0,1,1) outranks
         the bare class (0,1,0) regardless of order. If these rules are ever
         moved below the mobile block, the prefix becomes redundant but stays
         harmless — do not strip it in place.
      ════════════════════════════════════════ */
      #screen-contact {
        max-width: none;
        margin: 0;
        width: 100%;
        background: #f3f4f6;
      }

      /* The mobile topbar duplicates the sticky desktop header + the
         breadcrumb below it — hidden here, exactly as #screen-product does. */
      #screen-contact .chat-topbar { display: none; }

      #screen-contact .lb-contact-wrap {
        display: grid;
        grid-template-columns: minmax(0, 1fr) 320px;
        grid-template-areas:
          "crumb crumb"
          "hero  hero"
          "main  side";
        align-items: start;
        gap: 0 28px;
        width: 100%;
        max-width: 1180px;
        margin: 0 auto;
        padding: 20px 28px 44px;
      }

      #screen-contact .lb-contact-crumb { grid-area: crumb; display: flex; }
      #screen-contact .lb-contact-hero  { grid-area: hero; }
      #screen-contact .lb-contact-main  { grid-area: main; }
      #screen-contact .lb-contact-side  { grid-area: side; }

      #screen-contact .lb-contact-hero {
        align-items: center;
        padding: 24px 28px;
        margin-bottom: 20px;
      }
      #screen-contact .lb-contact-hero-icon { width: 48px; height: 48px; }
      #screen-contact .lb-contact-hero-icon svg { width: 25px; height: 25px; }
      #screen-contact .lb-contact-hero-title { font-size: 21px; }
      #screen-contact .lb-contact-hero-sub { font-size: 13.5px; max-width: 660px; }

      #screen-contact .lb-contact-card {
        padding: 28px 30px 26px;
        box-shadow: var(--shadow);
        margin-bottom: 0;
      }

      /* Roomier two-up rows now that the column is ~700px wide rather than a
         phone's ~360px. The 380px stacking breakpoint in the mobile rules can
         never match inside this column, so the pairs always sit side by side. */
      #screen-contact .lb-contact-row { gap: 18px; }
      #screen-contact .lb-contact-field { margin-bottom: 18px; }
      #screen-contact .lb-contact-label { font-size: 12.5px; margin-bottom: 7px; }
      #screen-contact .lb-contact-input { font-size: 14px; padding: 12px 14px; }
      #screen-contact .lb-contact-textarea { min-height: 180px; font-size: 14px; }
      #screen-contact .lb-contact-identity { padding: 12px 14px; font-size: 13px; }

      /* Full-width submit reads as a mobile pattern on a wide form — right-align
         it to a natural button width instead. */
      #screen-contact .lb-contact-btn {
        width: auto;
        min-width: 210px;
        padding: 13px 30px;
        float: right;
        transition: filter .15s ease;
      }
      #screen-contact .lb-contact-btn:hover { filter: brightness(1.08); }
      /* .lb-contact-privacy follows the floated button, so it needs to clear it
         or it wraps around the side. */
      #screen-contact .lb-contact-privacy {
        clear: both;
        padding-top: 18px;
        text-align: right;
      }

      /* The gate and confirmation stay centered blocks — their buttons are the
         primary action of the whole card, so full width is right there. */
      #screen-contact .lb-contact-locked { padding: 26px 6px 10px; }
      #screen-contact .lb-contact-locked .lb-contact-btn {
        float: none;
        width: 100%;
        max-width: 320px;
        margin-left: auto;
        margin-right: auto;
        display: block;
      }
      #screen-contact .lb-contact-locked-title { font-size: 18px; }

      /* Sticky rail — 108px clears the sticky header (60px) + subnav (38px),
         the same offset #screen-product's buy box uses. */
      #screen-contact .lb-contact-side {
        position: sticky;
        top: 108px;
      }
      #screen-contact .lb-contact-alt { gap: 12px; margin-bottom: 14px; }
      #screen-contact .lb-contact-alt-item {
        transition: border-color .15s, box-shadow .15s;
      }
      #screen-contact .lb-contact-alt-item:hover {
        border-color: var(--teal);
        box-shadow: 0 2px 10px rgba(15, 138, 131, .1);
      }

      /* Below 1040px there isn't room for a 320px rail beside a usable form —
         collapse to a single centered column (the rail falls under the form,
         which is the mobile order anyway). */
      @media (max-width: 1040px) {
        #screen-contact .lb-contact-wrap {
          grid-template-columns: minmax(0, 1fr);
          grid-template-areas: "crumb" "hero" "main" "side";
          max-width: 780px;
        }
        #screen-contact .lb-contact-side { position: static; margin-top: 16px; }
      }
    }

    @media (min-width: 1100px) and (min-height: 501px) {
      .grid { grid-template-columns: repeat(4, 1fr); }
      .desktop-header { padding: 0 40px; }
      .desktop-subnav { padding: 0 40px; }
      #screen-grid .banner { margin: 20px 40px 0; }
      #screen-grid .grid-wrap { padding: 16px 40px 24px; }
    }

    /* ══════════════════════════════════════════════════════════════════════
       PORTRAIT-ONLY LOCK (phones) — keep this LAST in the file
       ══════════════════════════════════════════════════════════════════════
       The app is designed vertical only. A real orientation lock isn't
       available in a normal browser tab (screen.orientation.lock() requires
       fullscreen and iOS Safari doesn't implement it at all), so instead the
       whole page is counter-rotated: when the phone is turned sideways the
       browser rotates the viewport, and we rotate the content back by the
       same amount, so nothing appears to happen. Turning the phone simply
       has no effect on what the user sees.

       Three things make it actually work:

       1. It must be the LAST block in this file. Its `body` and
          `.phone-shell` sizing has the same specificity as the generic
          `html, body { width:100%; height:100% }` and
          `.phone-shell { width:100vw; height:var(--app-h) }` rules, so
          whichever comes last wins. This block used to live at the top,
          which silently cancelled its own width/height and left the rotated
          box at the phone's physical landscape size.

       2. It rotates BODY, not .phone-shell. The phone/OTP modal overlays are
          siblings of .phone-shell, so rotating only the shell left them
          sideways. And because a transformed element becomes the containing
          block for its position:fixed descendants, rotating body makes every
          fixed overlay inside it (bottom nav, FAB, sheets, modals) land
          inside the rotated box instead of against the physical screen.

       3. It's gated on a short viewport HEIGHT, not merely
          orientation:landscape, so it only ever fires for a PHONE held
          sideways. Tablets and desktops in landscape have far more height,
          never match, and keep their (min-width:768px) desktop layout — the
          min-height:501px on those desktop queries is the other half of the
          same deal, stopping a ~844x390 sideways phone from being treated as
          a desktop while it's being rotated into a 390px-wide column.

       The two rotation directions correspond to the two ways a phone can be
       turned; lobbybuy.js puts .lb-rot-270 on <html> for the second one (see
       syncRotationClass) so the app stays upright either way. */
    @media (orientation: landscape) and (max-height: 500px) {
      html { overflow: hidden; height: 100%; }

      html body {
        position: fixed;
        top: 0; left: 0;
        /* Swapped on purpose: the app's width is the screen's height.
           svh/svw ("small" viewport units) size the app as if the mobile
           browser chrome is visible, so it is never clipped underneath a
           toolbar and never resizes as the toolbar hides/shows. The plain
           vh/vw pair above is the fallback for older browsers. */
        width: 100vh;  height: 100vw;
        width: 100svh; height: 100svw;
        transform-origin: top left;
        /* Phone turned counter-clockwise (screen's right edge is now up). */
        transform: rotate(90deg) translateY(-100%);
        overflow: hidden;
        display: flex;
        flex-direction: column;
      }

      /* Phone turned clockwise — mirror image of the above. */
      html.lb-rot-270 body { transform: rotate(-90deg) translateX(-100%); }

      /* .phone-shell defaults to 100vw x var(--app-h); inside the rotated
         body it just needs to fill its parent. */
      html .phone-shell { width: 100%; height: 100%; }
    }

    /* ══════════════════════════════════════════════════════════════════════
       CONTACT US  (#screen-contact)

       Scoped under .lb-contact-* so nothing here can leak into the checkout
       or address forms, which have their own input styling.
    ══════════════════════════════════════════════════════════════════════ */

    .lb-contact-wrap {
      padding: 14px var(--side-pad, 14px) 4px;
      max-width: 680px;
      margin: 0 auto;
    }

    /* Desktop-only — the mobile .chat-topbar already gives this screen a title
       and a back arrow, so the breadcrumb would be a duplicate. Turned on
       inside the min-width:768px query, mirroring .pd-desktop-breadcrumb. */
    .lb-contact-crumb {
      display: none;
      align-items: center;
      gap: 7px;
      font-size: 12.5px;
      color: var(--text-3);
      margin-bottom: 14px;
    }
    .lb-contact-crumb span:first-child { cursor: pointer; }
    .lb-contact-crumb span:first-child:hover { color: var(--teal); text-decoration: underline; }
    .lb-contact-crumb-sep { color: var(--border); }
    .lb-contact-crumb b { color: var(--text); font-weight: 700; }

    /* Plain wrappers on mobile — they carry no layout of their own here and
       exist so the desktop grid has two columns to place. */
    .lb-contact-main { display: block; }
    .lb-contact-side { display: block; }

    .lb-contact-info {
      background: var(--white);
      border: 1px solid var(--border);
      border-radius: var(--radius-lg);
      padding: 16px 16px 6px;
      margin-bottom: 18px;
    }
    .lb-contact-info-title {
      font-size: 12px;
      font-weight: 800;
      text-transform: uppercase;
      letter-spacing: .5px;
      color: var(--text-3);
      margin-bottom: 12px;
    }
    .lb-contact-info-row {
      display: flex;
      gap: 10px;
      font-size: 12.5px;
      line-height: 1.55;
      color: var(--text-2);
      margin-bottom: 14px;
    }
    .lb-contact-info-row b { color: var(--text); font-weight: 700; }
    .lb-contact-info-icon { flex-shrink: 0; font-size: 14px; line-height: 1.4; }

    .lb-contact-hero {
      display: flex;
      align-items: flex-start;
      gap: 14px;
      background: linear-gradient(135deg, var(--teal), var(--navy));
      border-radius: var(--radius-lg);
      padding: 18px 18px 20px;
      margin-bottom: 14px;
    }
    .lb-contact-hero-icon {
      flex-shrink: 0;
      width: 42px; height: 42px;
      border-radius: 12px;
      background: rgba(255, 255, 255, .16);
      display: flex; align-items: center; justify-content: center;
    }
    .lb-contact-hero-icon svg { width: 22px; height: 22px; }
    .lb-contact-hero-title { font-size: 17px; font-weight: 800; color: #fff; line-height: 1.3; }
    .lb-contact-hero-sub {
      font-size: 12.5px; line-height: 1.55;
      color: rgba(255, 255, 255, .78);
      margin-top: 5px;
    }

    .lb-contact-card {
      background: var(--white);
      border: 1px solid var(--border);
      border-radius: var(--radius-lg);
      padding: 18px 16px;
      margin-bottom: 14px;
    }

    /* The verified-email banner at the top of the form. This is display-only
       on purpose — the email the message is filed under comes from the bearer
       token server-side, so letting it be edited here would be a lie. */
    .lb-contact-identity {
      display: flex; align-items: center; gap: 10px;
      background: var(--teal-pale);
      border: 1px solid var(--teal-light);
      border-radius: var(--radius);
      padding: 10px 12px;
      margin-bottom: 16px;
      font-size: 12.5px;
      color: var(--text-2);
    }
    .lb-contact-identity b { color: var(--text); font-weight: 700; }
    .lb-contact-identity-badge {
      flex-shrink: 0;
      font-size: 10px; font-weight: 700;
      color: var(--teal-dark);
      background: var(--teal-light);
      border-radius: 99px;
      padding: 3px 8px;
      margin-left: auto;
      white-space: nowrap;
    }

    /* Two-up on anything with room, stacked on narrow phones. */
    .lb-contact-row { display: flex; gap: 12px; }
    .lb-contact-row > .lb-contact-field { flex: 1; min-width: 0; }
    @media (max-width: 380px) { .lb-contact-row { flex-direction: column; gap: 0; } }

    .lb-contact-field { margin-bottom: 14px; }

    .lb-contact-label {
      display: block;
      font-size: 12px; font-weight: 700;
      color: var(--text);
      margin-bottom: 6px;
    }
    .lb-contact-opt { font-weight: 500; color: var(--text-3); }

    .lb-contact-input {
      width: 100%;
      box-sizing: border-box;
      font-family: 'Inter', sans-serif;
      /* 16px minimum — anything smaller makes iOS Safari zoom the page in on
         focus, which on this fixed-height app shell leaves it zoomed and
         mis-scrolled after the keyboard closes. */
      font-size: 16px;
      color: var(--text);
      background: var(--white);
      border: 1.5px solid var(--border);
      border-radius: var(--radius);
      padding: 12px 13px;
      outline: none;
      transition: border-color .16s ease, box-shadow .16s ease;
      -webkit-appearance: none;
      appearance: none;
    }
    .lb-contact-input::placeholder { color: var(--text-3); }
    .lb-contact-input:focus {
      border-color: var(--teal);
      box-shadow: 0 0 0 3px rgba(15, 138, 131, .12);
    }

    .lb-contact-textarea { resize: vertical; min-height: 130px; line-height: 1.55; }

    .lb-contact-select-wrap { position: relative; }
    .lb-contact-select { padding-right: 38px; cursor: pointer; }
    .lb-contact-select-caret {
      position: absolute;
      right: 13px; top: 50%;
      transform: translateY(-50%);
      width: 16px; height: 16px;
      stroke: var(--text-3);
      fill: none;
      pointer-events: none;
    }

    .lb-contact-count {
      text-align: right;
      font-size: 11px;
      color: var(--text-3);
      margin-top: 5px;
    }

    .lb-contact-error {
      background: #FDECEC;
      border: 1px solid #F5C6C6;
      color: #A93232;
      border-radius: var(--radius);
      padding: 10px 12px;
      font-size: 12.5px;
      line-height: 1.5;
      margin-bottom: 12px;
    }

    .lb-contact-btn {
      width: 100%;
      padding: 14px;
      background: linear-gradient(135deg, var(--teal), var(--navy));
      color: #fff;
      border: none;
      border-radius: var(--radius);
      font-family: 'Inter', sans-serif;
      font-size: 15px; font-weight: 700;
      cursor: pointer;
    }
    .lb-contact-btn[disabled] { opacity: .6; cursor: default; }
    .lb-contact-btn--ghost {
      background: var(--white);
      color: var(--teal-dark);
      border: 1.5px solid var(--teal);
      margin-bottom: 10px;
    }

    .lb-contact-privacy {
      text-align: center;
      font-size: 11px;
      line-height: 1.55;
      color: var(--text-3);
      margin-top: 12px;
    }
    .lb-contact-privacy b { color: var(--text-2); }

    /* Shared layout for the signed-out gate and the sent confirmation. */
    .lb-contact-locked { text-align: center; padding: 12px 6px 4px; }
    .lb-contact-locked-icon { font-size: 34px; line-height: 1; margin-bottom: 12px; }
    .lb-contact-locked-title { font-size: 16px; font-weight: 800; color: var(--text); margin-bottom: 8px; }
    .lb-contact-locked-sub {
      font-size: 13px; line-height: 1.6;
      color: var(--text-2);
      margin: 0 auto 18px;
      max-width: 380px;
    }

    .lb-contact-alt { display: flex; flex-direction: column; gap: 10px; margin-bottom: 18px; }
    .lb-contact-alt-item {
      display: flex; align-items: center; gap: 12px;
      background: var(--white);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      padding: 13px 14px;
      cursor: pointer;
    }
    .lb-contact-alt-emoji { font-size: 20px; flex-shrink: 0; }

    /* ══════════════════════════════════════════════════════════════════════
       MOBILE — no site footer on the browse screens
       ══════════════════════════════════════════════════════════════════════
       These four keep their footer on DESKTOP (deleting the markup would take
       it from both), but drop it on phones, where every one of them sits
       directly above .bottom-nav. That bar's four items — Home / Categories /
       How it works / You — already cover the footer's whole Explore column,
       so on mobile the footer is a duplicate nav plus several hundred pixels
       of scroll between the user and the end of the list. Desktop has no
       .bottom-nav, so there the footer is the only place those links live.

       The condition is the exact inverse of the desktop query
       (min-width:768px AND min-height:501px): comma means OR, so this matches
       precisely when that one does not, and the two can never both apply.
       Written with #id .class (1,1,0) so it also outranks the plain
       .lb-footer rules regardless of where they sit in this file — the same
       cascade trap that silently half-applied the desktop contact layout. */
    @media (max-width: 767px), (max-height: 500px) {
      #screen-building .lb-footer,
      #screen-grid .lb-footer,
      #screen-product .lb-footer,
      #screen-categories .lb-footer,
      #screen-contact .lb-footer { display: none; }
    }
    .lb-contact-alt-title { font-size: 13.5px; font-weight: 700; color: var(--text); }
    .lb-contact-alt-sub { font-size: 11.5px; color: var(--text-3); margin-top: 2px; line-height: 1.45; }

    /* ═══════════════════════════════════════════════════════════════════════
       CATEGORIES SCREEN — photo-first tiles (2026-08-12)

       #screen-categories used to render 2-up white cards with a 56px circular
       avatar tucked in the corner. The category images are full-bleed square
       lifestyle crops, so shrinking them into a circle threw away the point of
       having them. These tiles let the photo BE the card: the image covers the
       tile, a bottom scrim carries the name and description, and the first
       category gets a wide hero tile so the grid reads as an editorial mosaic
       instead of a uniform sheet.

       Markup comes from _renderCatGrid() in lobbybuy/categories.js. Every rule
       here is a new class name, so nothing above can be affected.
       ═══════════════════════════════════════════════════════════════════════ */
    /* Scroll container for the whole screen. The bottom pad clears the fixed
       .bottom-nav: on mobile the .lb-footer that carries that reservation
       everywhere else (.lb-footer--nav) is display:none, so without this the
       last row of tiles sits underneath the nav bar and can't be scrolled into
       view. env() adds the iOS home-indicator strip on top of that. */
    .lb-catpage-scroll {
      flex: 1;
      overflow-y: auto;
      background: var(--surface);
      padding: 16px 16px calc(var(--nav-h, 56px) + 20px + env(safe-area-inset-bottom, 0px));
    }

    .lb-catpage-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }

    /* The AI-chat promo card at the top of the screen keeps its inline
       `grid-column:span 2`; this class exists so the desktop query below can
       widen it past 2 columns without fighting that inline style. */
    .lb-catpage-hero-promo { grid-column: span 2; }

    .lb-cattile {
      position: relative;
      overflow: hidden;
      border-radius: 16px;
      cursor: pointer;
      aspect-ratio: 1 / 1;
      background: var(--teal-pale);
      box-shadow: 0 1px 3px rgba(0, 0, 0, .09);
      -webkit-tap-highlight-color: transparent;
      transition: box-shadow .2s ease, transform .2s ease;
    }
    .lb-cattile:active { transform: scale(.975); }

    /* Lead tile: full width, cinematic crop. */
    .lb-cattile-wide { grid-column: span 2; aspect-ratio: 16 / 9; }

    .lb-cattile-photo {
      position: absolute; inset: 0;
      width: 100%; height: 100%;
      object-fit: cover; display: block;
      transition: transform .4s ease;
    }
    .lb-cattile:hover .lb-cattile-photo { transform: scale(1.06); }

    /* No image_url on the category → the emoji on a soft tinted wash, so the
       tile still has presence instead of rendering as an empty grey box. */
    .lb-cattile-fallback {
      position: absolute; inset: 0;
      display: flex; align-items: center; justify-content: center;
      font-size: 54px; line-height: 1;
      background: linear-gradient(145deg, var(--teal-pale), #ffffff 75%);
    }
    .lb-cattile-wide .lb-cattile-fallback { font-size: 64px; }

    /* Multi-stop, not a plain 50% fade: the text sits on real darkness at the
       very bottom while the top two-thirds of the photo stays untouched. */
    .lb-cattile-scrim {
      position: absolute; inset: 0;
      background: linear-gradient(to top,
        rgba(8, 30, 28, .86) 0%,
        rgba(8, 30, 28, .52) 34%,
        rgba(8, 30, 28, .10) 62%,
        rgba(8, 30, 28, 0) 82%);
      pointer-events: none;
    }

    .lb-cattile-body {
      position: absolute; left: 0; right: 0; bottom: 0;
      padding: 12px 12px 11px;
    }
    .lb-cattile-name {
      font-size: 15px; font-weight: 800; color: #fff;
      line-height: 1.22; letter-spacing: -.01em;
      text-shadow: 0 1px 4px rgba(0, 0, 0, .4);
      display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
      overflow: hidden; overflow-wrap: anywhere;
    }
    .lb-cattile-desc {
      font-size: 11px; color: rgba(255, 255, 255, .85);
      margin-top: 3px; line-height: 1.35;
      text-shadow: 0 1px 3px rgba(0, 0, 0, .45);
      display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
      overflow: hidden;
    }
    /* Square tiles are tight — the description is the first thing to give, so
       a long one can never push the name off the tile. */
    .lb-cattile:not(.lb-cattile-wide) .lb-cattile-desc { -webkit-line-clamp: 1; }

    .lb-cattile-wide .lb-cattile-body { padding: 16px 18px 15px; }
    .lb-cattile-wide .lb-cattile-name { font-size: 20px; }
    .lb-cattile-wide .lb-cattile-desc { font-size: 12.5px; max-width: 72%; }

    /* "Shop" chip — a small affordance in the corner so the tile still reads
       as tappable now that the white card and its border are gone. */
    .lb-cattile-chip {
      position: absolute; top: 10px; right: 10px;
      display: inline-flex; align-items: center; gap: 4px;
      height: 24px; padding: 0 9px;
      border-radius: 99px;
      background: rgba(255, 255, 255, .92);
      color: var(--text);
      font-size: 10.5px; font-weight: 700;
      box-shadow: 0 1px 4px rgba(0, 0, 0, .18);
      pointer-events: none;
    }
    .lb-cattile-chip svg { width: 10px; height: 10px; stroke: currentColor; fill: none; stroke-width: 3; }

    /* Desktop: same condition as the main desktop block (min-width AND
       min-height), so the two can never disagree about which layout is live.
       #screen-categories is capped at 760px up there, so three columns is the
       most these tiles can take without going postage-stamp again. */
    @media (min-width: 768px) and (min-height: 501px) {
      /* .bottom-nav is display:none here and the footer is visible again with
         its own padding-bottom, so the mobile nav reservation must come back
         off — otherwise the screen ends in a band of dead space. */
      .lb-catpage-scroll { padding-bottom: 16px; }
      .lb-catpage-grid { grid-template-columns: repeat(3, 1fr); gap: 16px; }
      .lb-catpage-hero-promo { grid-column: 1 / -1; }
      .lb-cattile-wide { grid-column: span 3; aspect-ratio: 21 / 9; }
      .lb-cattile:hover { box-shadow: 0 8px 22px rgba(0, 0, 0, .16); }
      .lb-cattile-name { font-size: 16px; }
      .lb-cattile:not(.lb-cattile-wide) .lb-cattile-desc { -webkit-line-clamp: 2; }
      .lb-cattile-wide .lb-cattile-name { font-size: 24px; }
      .lb-cattile-wide .lb-cattile-desc { font-size: 13px; max-width: 60%; }
    }

    /* ══════════════════════════════════════════════════════════════════════
       Event activity — unlocked-price card stack (#status-cards)

       A product that has already won one or more price drops this cycle gets
       extra card edges peeking out from underneath it, one per drop (capped at
       two by _renderStatusCards). The edges carry no text: they are there to
       read as "there is another card under this one", and tapping them opens
       the price history that explains why. A product with no drops has no
       edges and no hit area, so it renders exactly as it always did.
       ══════════════════════════════════════════════════════════════════════ */
    .lbstk {
      position: relative;
      user-select: none;
      -webkit-user-select: none;
      -webkit-touch-callout: none;
      -webkit-tap-highlight-color: transparent;
    }
    .lbstk-deck { position: relative; }
    .lbstk:has(.lbstk-drawer) { cursor: pointer; }
    .lbstk-deck .lbstk-card { cursor: pointer; }

    /* Reserves the strip the edges stick out into. Without it the edges would
       eat into the 10px gap #status-cards puts between rows and collide with
       the next card. */
    .lbstk:has(.lbstk-edge) { padding-bottom: 14px; }

    .lbstk-edge {
      position: absolute; z-index: 0;
      left: 6px; right: 6px; bottom: 0;
      height: 14px;
      background: #FFDE8A;
      border: 1px solid #E0B240;
      border-top: 0;
      border-radius: 0 0 12px 12px;
      box-shadow: 0 2px 5px rgba(146, 64, 14, .15);
    }

    /* The card keeps every inline style _renderStatusCards writes; only the
       radius moved here so the bottom corners can square off while open. */
    .lbstk-card {
      position: relative; z-index: 2;
      cursor: default;
      border-radius: 12px;
      transition: border-radius .26s cubic-bezier(.65, 0, .35, 1),
                  box-shadow .3s cubic-bezier(.65, 0, .35, 1);
    }

    /* Invisible tap target over the exposed edges (plus a few px of the card's
       own bottom lip, which is easier to hit than a 13px strip alone). */
    .lbstk-hit {
      position: absolute; z-index: 3;
      left: 0; right: 0; bottom: -4px; height: 34px;
      cursor: pointer;
      -webkit-tap-highlight-color: transparent;
    }
    .lbstk-hit:focus-visible { outline: 2px solid var(--teal); outline-offset: 2px; border-radius: 8px; }

    .lbstk.is-open .lbstk-card {
      border-bottom-left-radius: 0; border-bottom-right-radius: 0;
      box-shadow: 0 3px 6px rgba(23, 50, 77, .10);
    }


    /* ── the drawer ─────────────────────────────────────────────────────── */
    .lbstk-drawer {
      position: relative; z-index: 1;
      margin: 0 6px;
      height: 0; overflow: hidden;
      background: #fff;
      border-left: 1px solid #E0B240;
      border-right: 1px solid #E0B240;
      transition: height .3s cubic-bezier(.65, 0, .35, 1);
    }
    .lbstk.is-open .lbstk-drawer {
      transition: height .38s cubic-bezier(.33, 1, .68, 1);
    }
    .lbstk-drawer-in {
      min-height: 0;
      padding: 13px 14px 14px;
      transform: translateY(-6px);
      opacity: 0;
      transition: transform .2s cubic-bezier(.65, 0, .35, 1), opacity .16s ease-in;
    }
    .lbstk.is-open .lbstk-drawer-in {
      transform: translateY(0);
      opacity: 1;
      transition: transform .34s cubic-bezier(.33, 1, .68, 1) .05s, opacity .26s ease-out .05s;
    }

    @media (prefers-reduced-motion: reduce) {
      .lbstk-drawer, .lbstk-drawer-in, .lbstk-edge, .lbstk-card { transition: none; }
      .lbstk-drawer-in { transform: none; opacity: 1; }
    }
    .lbstk-title {
      font-size: 10px; font-weight: 800; letter-spacing: .8px;
      text-transform: uppercase; color: var(--text-3);
      margin-bottom: 12px;
    }

    /* Vertical thread: teal down to the last win, grey for what is still ahead.
       The gradient stop is set from the row count in _priceHistoryHTML's markup
       order — anything below the last .is-won row reads as not-yet-reached. */
    .lbstk-thread { position: relative; padding-left: 26px; }
    .lbstk-thread::before {
      content: ""; position: absolute; left: 7px; top: 9px; bottom: 16px; width: 2px;
      background: #D7E3E5;
    }
    .lbstk-row { position: relative; padding-bottom: 13px; }
    .lbstk-row:last-child { padding-bottom: 0; }
    .lbstk-node {
      position: absolute; left: -26px; top: 2px;
      width: 16px; height: 16px; border-radius: 50%;
      background: #fff; border: 2px solid #CFDCDF;
      box-sizing: border-box;
    }
    .lbstk-row.is-won .lbstk-node {
      background: var(--teal); border-color: var(--teal); color: #fff;
      font-size: 9px; font-weight: 900; line-height: 1;
      display: flex; align-items: center; justify-content: center;
    }
    .lbstk-row.is-next .lbstk-node {
      border-color: var(--navy, #14304A);
      box-shadow: 0 0 0 3px rgba(20, 48, 74, .10);
    }
    .lbstk-l1 { display: flex; align-items: baseline; gap: 8px; }
    .lbstk-price { font-size: 15px; font-weight: 800; color: var(--text-2, #4A5A64); }
    .lbstk-row.is-start .lbstk-price { color: var(--text-3); text-decoration: line-through; font-weight: 700; }
    .lbstk-row.is-won   .lbstk-price { color: var(--teal); }
    .lbstk-row.is-next  .lbstk-price { color: var(--navy, #14304A); }
    .lbstk-row.is-locked .lbstk-price { color: var(--text-3); }
    .lbstk-badge {
      font-size: 9.5px; font-weight: 800; letter-spacing: .5px; text-transform: uppercase;
      color: var(--text-3); background: #EDF2F3;
      border-radius: 5px; padding: 2px 7px; white-space: nowrap;
    }
    .lbstk-row.is-won  .lbstk-badge { color: var(--teal); background: var(--teal-pale, #E1F1F0); }
    .lbstk-row.is-next .lbstk-badge { color: #fff; background: var(--navy, #14304A); }
    .lbstk-l2 { font-size: 11.5px; color: var(--text-3); margin-top: 2px; }

    .lbstk-saved {
      margin-top: 13px; padding: 10px 12px;
      background: var(--teal-pale, #E6F4F3); border-radius: 10px;
      display: flex; align-items: center; gap: 9px;
      font-size: 12px; font-weight: 700; color: var(--teal);
    }
    .lbstk-saved b { margin-left: auto; font-size: 15px; font-weight: 900; }

    /* ── My orders — the same blade on an active order card ─────────────
       The active-order card (checkout.js orderCardHtml) reuses the .lbstk
       markup wholesale: its face shows only the total, and the yellow handle
       opens the price breakdown + "Edit order" underneath. Only the geometry
       differs — order cards are 14px-round, not 12px — plus a closed state for
       the duration of an inline edit, when the card grows its own totals and
       buttons and the blade would be a duplicate of them. */
    .lbstk-order .lbstk-card { border-radius: 14px; }
    .lbstk-order.is-open .lbstk-card {
      border-bottom-left-radius: 0; border-bottom-right-radius: 0;
    }
    /* The per-cycle delivery card ("Arriving Saturday, Aug 22") wears the same
       blade when that cycle has locked orders: pulling it open reveals the
       orders already being prepared, which can no longer be edited and so have
       no place in the Active list above. Same 14px radius as the card. */
    .lbstk-cycle .lbstk-card { border-radius: 14px; }
    .lbstk-cycle.is-open .lbstk-card {
      border-bottom-left-radius: 0; border-bottom-right-radius: 0;
    }
    /* The order cards inside carry their own 12px bottom margin — the drawer
       doesn't need to pad the same gap twice. */
    .lbstk-cycle .lbstk-drawer-in { padding: 12px 10px 2px; }

    /* The Arriving bucket wears the blade too, at the bucket card's own 12px
       radius, so dispatched orders open with the same pull as everything else
       here. Its chevron flips instead of swapping "Show ▼"/"Hide ▲" text — the
       handle already says which way this goes. */
    .lbstk-bucket .lbstk-chev {
      transition: transform .3s cubic-bezier(.65, 0, .35, 1);
    }
    .lbstk-bucket.is-open .lbstk-chev { transform: rotate(180deg); }
    .lbstk-bucket .lbstk-drawer-in { padding: 12px 8px 10px; }

    .lbstk-order.is-editing .lbstk-edge,
    .lbstk-order.is-editing .lbstk-drawer,
    .lbstk-order.is-editing .lbstk-hit { display: none; }
    .lbstk-order.is-editing { padding-bottom: 0; }

    /* Fallback for browsers without :has() — reserve the strip on every deck.
       Flat cards get 13px of harmless extra bottom padding rather than the
       stacked ones getting clipped. */
    @supports not selector(:has(*)) {
      .lbstk-deck { padding-bottom: 23px; }
    }
