  /* ── Local token overrides ────────────────────────────────────────────────
     styles.css is loaded FIRST on this page and already defines every token
     below; this block only exists to shift a few of them for the browse
     layout. Treat it as a diff, not a second source of truth — anything
     restated here has to be restated in builder.css too, and any token that
     is NOT deliberately different should simply be deleted from this block so
     styles.css owns it.

     --text-muted is the one that went wrong: this file said #AFAFAF (2.1:1)
     and styles.css said #8A8A8A, so the "185 PACKS" pill, the category rail
     labels and the sidebar counts were painted with the least legible of the
     three values on the site's busiest page. It is now pinned to exactly the
     styles.css value in both themes, and must stay pinned. */
  :root {
    --white:#FFFFFF;--text:#1A1A1A;--text-soft:#3D3D3D;
    --text-muted:#6E6E78;--border:#ECECEC;--cream:#F7F5F0;
    --radius:16px;--radius-sm:12px;
    --bg:#FAFAFA;
  }
  body.dark{
    --white:#18181C;--text:#F2F2F0;--text-soft:#B0B0B8;
    --text-muted:#8A8A94;--border:#26262B;--cream:#141416;
    /* #0E0E10, matching styles.css / builder.css / dashboard.css / rewards.css.
       This sat on #0f0f11 — one step off the shared dark background on the
       site's busiest page. */
    --bg:#0E0E10;
  }
  *,*::before,*::after{box-sizing:border-box;}

  /* Skeleton shimmer (.skel / @keyframes sh-shimmer) is injected once,
     globally, by header.js — do not redefine it here. header.js runs
     synchronously before this page's <body> is parsed, so there's no flash;
     a second local copy previously caused the shimmer to render as a static
     frame instead of animating (two stylesheets racing to own the same
     @keyframes name). */

  body{margin:0;background:var(--bg) !important;color:var(--text);font-family:'Geist','DM Sans',sans-serif;min-height:100vh;}

  /* ── Toolbar — no background, just spacing ── */
  .packs-toolbar{
    display:flex;flex-direction:column;gap:0;
    position:sticky;top:64px;
    z-index:995;
    background:none;
    backdrop-filter:none;-webkit-backdrop-filter:none;
    box-shadow:none;
    transition:none;
    width:85%;max-width:1400px;margin:0 auto;
    padding:0;
  }
  @media(max-width:1024px){
    .packs-toolbar{width:100%;padding:0 16px;top:0;}
  }

  .packs-toolbar-top{
    display:flex;align-items:center;justify-content:space-between;
    min-height:48px;padding:8px 0;position:relative;
  }
  .packs-toolbar-left{display:flex;align-items:center;gap:0;flex-shrink:1;min-width:0;overflow:hidden;}
  /* Inline title tabs — 14px to match index.html left section width */
  .packs-title-tabs{display:flex;align-items:center;gap:6px;white-space:nowrap;}
  .packs-title-tab{
    font-family:'Geist','DM Sans',sans-serif;font-size:22px;font-weight:500;
    color:var(--text-muted);letter-spacing:-0.02em;line-height:1;
    border:none;background:none;cursor:pointer;padding:0 4px 0 0;
    transition:color .15s;white-space:nowrap;
  }
  .packs-title-tab:hover{color:var(--text);}
  .packs-title-tab.active{font-weight:700;color:var(--text);}
  body.dark .packs-title-tab{color:var(--text-muted);}
  body.dark .packs-title-tab:hover{color:#F2F2F0;}
  body.dark .packs-title-tab.active{color:#F2F2F0;}
  .packs-title-sep{
    font-size:17px;color:var(--text-muted);opacity:0.35;
    padding:0 4px;line-height:1;pointer-events:none;
  }
  .packs-toolbar-count{
    display:inline-flex;align-items:center;margin-left:8px;
    background:rgba(0,0,0,0.04);border:1.5px solid var(--border);
    border-radius:50px;padding:2px 8px;
    font-family:'Geist','DM Sans',sans-serif;font-size:12px;font-weight:700;color:var(--text-muted);
  }
  body.dark .packs-toolbar-count{background:rgba(255,255,255,0.05);}

  /* ── Sticky search bar (matches builder.html) ── */
  .packs-search-wrap{
    position:sticky;top:64px;z-index:990;
    background:var(--bg,#F9F9F7);
    padding:0 0 12px;margin-bottom:0;
    width:100%;
  }
  body.dark .packs-search-wrap{background:#0e0e10;}
  .packs-search-container{
    display:flex;align-items:center;
    width:85%;max-width:1400px;margin-left:auto;margin-right:auto;
  }
  .packs-search-inner{position:relative;display:flex;align-items:center;flex:1;min-width:0;}
  .packs-search-icon{position:absolute;left:12px;color:#AFAFAF;pointer-events:none;display:flex;align-items:center;}
  .packs-search-input{
    width:100%;height:38px;border:1.5px solid var(--border);border-radius:12px;
    padding:0 32px 0 36px;font-family:'DM Sans',sans-serif;font-size:13.5px;
    color:var(--text);background:var(--white);outline:none;
    transition:border-color .15s,box-shadow .15s;
  }
  .packs-search-input:focus{border-color:var(--pp-green-600);box-shadow:0 0 0 3px rgba(var(--pp-green-600-rgb), 0.09);}
  .packs-search-input::placeholder{color:var(--text-muted);}
  body.dark .packs-search-input{background:#141416;border-color:#26262B;color:#F2F2F0;}
  body.dark .packs-search-input:focus{border-color:var(--pp-green-400);box-shadow:0 0 0 3px rgba(var(--pp-green-400-rgb), 0.1);}
  .packs-search-clear{
    position:absolute;right:8px;width:20px;height:20px;border:none;background:none;
    cursor:pointer;padding:0;color:#AFAFAF;display:none;align-items:center;justify-content:center;
    border-radius:50%;transition:color .12s,background .12s;font-size:16px;line-height:1;
  }
  .packs-search-clear:hover{color:#555;background:rgba(0,0,0,0.07);}
  body.dark .packs-search-clear:hover{color:#ddd;background:rgba(255,255,255,0.08);}
  @media(max-width:1024px){
    .packs-search-wrap{padding:10px 16px 12px;}
    .packs-search-container{width:100%;}
  }
  /* The site header is 64px on desktop but 59px once the mobile nav kicks in
     (≤999.98px). Stick the search bar right under it — top:0 made it hide behind
     the fixed header on phones; the old 64px left a 5px gap on tablets. */
  @media(max-width:999.98px){.packs-search-wrap{top:59px;}}
  @media(max-width:768px){
    .packs-search-container{flex-wrap:wrap;}
    .packs-search-inner{flex:1 1 100%;}
    .packs-view-wrap{flex:1 1 100%;}
    .packs-view-btn{width:100%;}
    .packs-view-dropdown{width:100%;left:0 !important;right:0 !important;}
  }



  /* ── View dropdown (Official / Saved) ── */
  .packs-view-wrap{position:relative;flex-shrink:0;}
  .packs-view-btn{
    height:38px;min-width:140px;padding:0 10px 0 13px;
    border:1.5px solid var(--border);border-radius:12px;
    background:var(--white);font-family:'DM Sans',sans-serif;
    font-size:13px;font-weight:700;color:var(--text);cursor:pointer;
    display:flex;align-items:center;justify-content:space-between;gap:8px;
    transition:border-color .15s;white-space:nowrap;
  }
  .packs-view-btn:hover,.packs-view-btn.open{border-color:var(--pp-green-600);}
  body.dark .packs-view-btn{background:#141416;border-color:#26262B;color:#F2F2F0;}
  .packs-view-dropdown{
    position:absolute;top:calc(100% + 6px);left:0;min-width:170px;
    background:#fff;border-radius:14px;
    box-shadow:0 4px 6px rgba(0,0,0,.07),0 12px 32px rgba(0,0,0,.13);
    z-index:200;padding:6px;display:none;flex-direction:column;
  }
  .packs-view-dropdown.open{display:flex;}
  body.dark .packs-view-dropdown{background:#1e1e22;box-shadow:0 4px 6px rgba(0,0,0,.3),0 12px 32px rgba(0,0,0,.4);}
  .packs-view-opt{
    padding:9px 12px;border:none;background:none;
    font-family:'DM Sans',sans-serif;font-size:13.5px;font-weight:600;
    color:#1A1A1A;cursor:pointer;text-align:left;border-radius:9px;
    transition:background .1s;white-space:nowrap;
    display:flex;align-items:center;gap:8px;
  }
  .packs-view-opt:hover{background:#F4F4F3;}
  /* Neutral pill, not brand green — matches builder.html's .bb-cat-opt.active
     (frontend/builder.css). The sort dropdown isn't a category filter, so an
     active sort item is not a "you're in this category" signal the way green
     is used elsewhere on the page; it previously stood out as the one green
     highlight not tied to a category. */
  .packs-view-opt.active{background:rgba(0,0,0,.05);color:var(--text);font-weight:700;}
  body.dark .packs-view-opt{color:#F2F2F0;}
  body.dark .packs-view-opt:hover{background:rgba(255,255,255,.06);}
  body.dark .packs-view-opt.active{background:rgba(255,255,255,.07);color:var(--text);}

  /* Right controls */
  .packs-toolbar-right{display:flex;align-items:center;gap:12px;flex-shrink:0;}

  /* Sort + Filter buttons — same style as index.html */
  .pp-sortbtn-wrap{position:relative;}
  .product-sort-wrap{
    display:inline-flex;align-items:center;height:34px;
    padding:0 12px;border-radius:999px;border:1.5px solid var(--border);
    background:var(--white);cursor:pointer;gap:7px;font-family:'Geist','DM Sans',sans-serif;
  }
  body.dark .product-sort-wrap{background:#141416;color:#F2F2F0;}
  .product-sort-label{font-size:12px;font-weight:600;color:var(--text-muted);}
  body.dark .product-sort-label{color:var(--text-muted);}
  #packsSortVal{font-size:13px;font-weight:700;color:#1A1A1A;}
  body.dark #packsSortVal{color:#F2F2F0;}
  .packs-sort-ico{display:none;flex-shrink:0;color:var(--text-soft);}
  .pp-sort-menu{
    display:none;position:absolute;right:0;top:calc(100% + 8px);z-index:300;
    background:#fff;border:1.5px solid var(--border);border-radius:14px;
    box-shadow:0 18px 40px -16px rgba(20,20,30,0.28),0 4px 10px rgba(20,20,30,0.06);
    padding:6px;min-width:200px;
  }
  body.dark .pp-sort-menu{background:#141416;border-color:#26262B;}
  .pp-sort-menu.open{display:block;}
  .pp-sort-item{
    display:flex;align-items:center;justify-content:space-between;
    width:100%;padding:8px 12px;border-radius:9px;border:none;background:none;
    font-family:'Geist','DM Sans',sans-serif;font-size:13px;font-weight:600;
    color:#3D3D3D;cursor:pointer;text-align:left;
  }
  .pp-sort-item:hover{background:rgba(0,0,0,0.04);}
  body.dark .pp-sort-item{color:#B0B0B8;}
  body.dark .pp-sort-item:hover{background:rgba(255,255,255,0.05);}
  .pp-sort-tick{display:none;width:14px;height:14px;color:var(--accent);}
  .pp-sort-item.active .pp-sort-tick{display:block;}
  .product-sort-wrap.has-filters{border-color:var(--accent);color:var(--accent);background:rgba(var(--pp-green-600-rgb), 0.06);}

  /* Filter dropdown */
  .packs-filter-wrap{position:relative;}
  .packs-filter-dd{
    display:none;position:absolute;right:0;top:calc(100% + 8px);z-index:300;
    background:#fff;border:1.5px solid var(--border);border-radius:14px;
    box-shadow:0 18px 40px -16px rgba(20,20,30,0.28),0 4px 10px rgba(20,20,30,0.06);
    padding:12px;min-width:220px;
  }
  body.dark .packs-filter-dd{background:#141416;border-color:#26262B;}
  .packs-filter-dd.open{display:block;}
  .packs-filter-label{
    font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:.07em;
    color:var(--text-muted);margin-bottom:8px;
  }
  .packs-filter-pills{display:flex;flex-wrap:wrap;gap:5px;}
  .packs-filter-pill{
    display:inline-flex;align-items:center;height:28px;padding:0 11px;
    border-radius:999px;border:1.5px solid var(--border);
    background:var(--white);font-family:'Geist','DM Sans',sans-serif;
    font-size:12px;font-weight:600;color:#6B6B7B;cursor:pointer;
    transition:all .15s;white-space:nowrap;
  }
  .packs-filter-pill:hover{border-color:#AFAFAF;color:var(--text);}
  .packs-filter-pill.active{background:var(--text);color:#fff;border-color:var(--text);}
  body.dark .packs-filter-pill{background:#1d1c24;border-color:#2E2E34;color:#888890;}
  body.dark .packs-filter-pill:hover{border-color:#888890;color:var(--text);}
  body.dark .packs-filter-pill.active{background:var(--text);color:#0E0E10;border-color:var(--text);}
  .packs-filter-reset{
    font-family:'Geist','DM Sans',sans-serif;font-size:12px;font-weight:600;
    color:var(--text-muted);background:none;border:none;cursor:pointer;
    padding:4px 0;margin-top:8px;text-decoration:underline;text-underline-offset:2px;
    display:block;transition:color .15s;
  }
  .packs-filter-reset:hover{color:#EF4444;}

  /* ── Page header ── */
  .packs-page-header{
    width:85%;
    max-width:1400px;
    margin:var(--page-header-margin-top,6px) auto var(--page-header-margin-bottom,12px);
    box-sizing:border-box;
    display:flex;align-items:flex-end;justify-content:space-between;gap:16px;
  }
  @media(max-width:1024px){.packs-page-header{width:100%;padding:0 16px;}}
  /* Match builder.html's fullscreen desktop spacing (see .bb-page-header in
     builder.css @media(min-width:1025px)): no extra top margin, larger bottom
     margin, so the two pages' hero header sits at the same height and the
     gap down to the content grid lines up pixel-for-pixel. */
  @media(min-width:1025px){.packs-page-header{margin:0 auto 8px auto;}}
  .packs-page-left{display:flex;flex-direction:row;align-items:center;gap:12px;}
  /* No visible page title (like Pack Builder and Housing): the nav's Browse
     tab says where you are. The header stays in the DOM, off-screen, so the
     h1 is still there for screen readers and search. */
  .packs-page-header{
    position:absolute !important;width:1px !important;height:1px !important;margin:-1px !important;
    padding:0 !important;overflow:hidden !important;clip:rect(0 0 0 0);white-space:nowrap;border:0;
  }
  .packs-title-row{
    display:flex;align-items:center;gap:0;
    margin:0;
  }
  .packs-page-h1{
    font-family:'Inter','Geist',sans-serif;font-size:var(--page-title-size,34px);font-weight:var(--page-title-weight,800);
    color:var(--text);margin:0;letter-spacing:var(--page-title-letter-spacing,-0.02em);line-height:var(--page-title-line-height,1.1);
    cursor:pointer;
  }
  .packs-title-sep-slash{
    font-family:'Inter','Geist',sans-serif;font-size:34px;font-weight:300;
    color:var(--text-muted);margin:0 8px;opacity:0.4;line-height:1.1;
  }
  .packs-page-h1.dimmed{color:var(--text-muted);font-weight:600;opacity:0.5;font-size:34px;}
  .packs-count-pill{
    display:inline-flex;align-items:center;
    background:none;border:0;border-left:1px solid var(--border);
    border-radius:0;padding:1px 0 1px 10px;
    font-family:'Geist','DM Sans',sans-serif;font-size:12px;font-weight:650;
    color:var(--text-muted);width:fit-content;
    letter-spacing:0;
  }
  body.dark .packs-count-pill{background:none;}
  .packs-page-right{display:flex;align-items:center;gap:8px;margin-bottom:0;}

  /* ── Main content ── */
  .packs-wrap{
    background:none;
    border:none;
    box-shadow:none;
    width:85%;
    max-width:1400px;
    margin:0 auto 40px auto;
    padding:0 0 40px;
    box-sizing:border-box;
  }
  body.dark .packs-wrap{background:none;}
  @media(max-width:1024px){.packs-wrap{width:100%;padding:16px 0 40px;}}

  /* New pack banner */
  .new-pack-banner{
    display:flex;align-items:center;gap:12px;
    padding:14px 18px;border-radius:12px;margin-bottom:22px;
    width:fit-content;max-width:100%;
    background:rgba(37,99,235,.07);border:1.5px solid rgba(37,99,235,.2);
    font-family:'Geist','DM Sans',sans-serif;font-size:13px;font-weight:600;color:#1D4ED8;
    animation:bannerIn .4s cubic-bezier(.34,1.3,.64,1);
  }
  body.dark .new-pack-banner{background:rgba(96,165,250,.1);border-color:rgba(96,165,250,.25);color:#60A5FA;}
  @keyframes bannerIn{from{opacity:0;transform:translateY(-8px);}to{opacity:1;transform:translateY(0);}}
  .new-pack-banner-ico{font-size:18px;flex-shrink:0;}
  .new-pack-banner-close{
    margin-left:auto;background:none;border:none;cursor:pointer;
    color:currentColor;opacity:.6;font-size:16px;padding:0 4px;line-height:1;
  }
  .new-pack-banner-close:hover{opacity:1;}

  /* Grid */
  .packs-grid{
    display:grid;
    grid-template-columns:repeat(auto-fill,minmax(min(205px,100%),1fr));
    gap:18px;
  }
  .packs-load-more{display:flex;justify-content:center;padding:28px 0 8px;}
  .packs-load-more[hidden]{display:none;}
  .packs-load-more-btn{
    min-height:42px;padding:0 20px;border-radius:12px;
    border:1px solid var(--border);background:var(--white);color:var(--text);
    font:700 13px 'Geist','DM Sans',sans-serif;cursor:pointer;
    box-shadow:0 5px 16px rgba(15,23,42,.05);
    transition:border-color .15s,transform .15s,background .15s;
  }
  .packs-load-more-btn:hover{border-color:var(--pp-green-600);transform:translateY(-1px);}
  .packs-load-more-btn:focus-visible{outline:2px solid var(--pp-green-600);outline-offset:3px;}
  body.dark .packs-load-more-btn{background:#18181C;box-shadow:none;}
  .packs-load-sentinel{height:1px;width:100%;}

  /* ── Card reveal system (staggered wave, scroll-driven) ──
     .pp-reveal-pre hides a freshly-inserted card until the IntersectionObserver
     hands it a slot in the wave; .pp-reveal-in plays the entrance. The `both`
     fill keeps a delayed card at the from-frame until its turn. */
  @keyframes ppCardReveal {
    from { opacity:0; transform:translateY(18px) scale(.96); }
    to   { opacity:1; transform:translateY(0)    scale(1);   }
  }
  .pp-reveal-pre{opacity:0;}
  .pp-reveal-in{animation:ppCardReveal .5s cubic-bezier(.25,.46,.45,.94) both;}
  @media (prefers-reduced-motion: reduce){
    .pp-reveal-pre{opacity:1;}
    .pp-reveal-in{animation:none;}
  }

  /* ── Category sidebar layout ── */
  .packs-layout{display:flex;align-items:flex-start;gap:28px;}
  .packs-content{flex:1;min-width:0;}
  .packs-sidebar{
    width:260px;flex-shrink:0;
    display:flex;flex-direction:column;gap:2px;
    position:sticky;top:84px;
    border-right:1.5px solid var(--border);
    padding-right:16px;
    /* Sticky alone doesn't stop the column from being taller than the
       viewport — on a short window the category list pushed the Order/Edit
       buttons below the visible area with no way to scroll to them. Bound
       the column and let the list (the one part with unbounded length)
       scroll internally instead. */
    max-height:calc(100vh - 84px - 24px);
    overflow:hidden;
  }
  /* The category list is the unbounded part of this column — it scrolls on
     its own so Personal Packs/Favourites/Sale above and Add Category/Order/
     Edit below always stay in view. */
  #packsCatList{
    flex:1 1 auto;
    min-height:40px;
    overflow-y:auto;
    overflow-x:hidden;
    scrollbar-width:thin;
  }
  .packs-cat-add-btn,
  .packs-cat-clear-zone,
  .packs-cat-edit-btn{
    flex-shrink:0;
  }

  .packs-sidebar-indicator{
    position:absolute;
    right:-1.5px;
    width:2px;
    background:var(--text);
    border-radius:99px;
    transition:transform .25s cubic-bezier(0.4, 0, 0.2, 1), height .25s cubic-bezier(0.4, 0, 0.2, 1), opacity .15s;
    pointer-events:none;
    z-index:10;
    opacity:0;
  }
  .packs-cat-item{
    display:flex;align-items:center;justify-content:space-between;gap:8px;
    width:100%;padding:9px 10px;border:none;background:none;border-radius:8px;
    font-family:'Geist','DM Sans',sans-serif;font-size:14px;font-weight:500;
    color:var(--text-soft);cursor:pointer;text-align:left;
    transition:background .15s,color .15s;
  }
  .packs-cat-item:hover{background:rgba(0,0,0,0.04);color:var(--text);}
  body.dark .packs-cat-item:hover{background:rgba(255,255,255,0.05);}
  .packs-cat-item.active{color:var(--text);font-weight:700;background:rgba(0,0,0,0.03);}
  /* Loading rows in #packsCatList: a real row's height, name left, count right. */
  .packs-cat-skel{display:flex;align-items:center;justify-content:space-between;width:100%;padding:12px 10px;box-sizing:border-box;}
  body.dark .packs-cat-item.active{background:rgba(255,255,255,0.04);}
  .packs-cat-item:disabled,
  .packs-cat-item.disabled{
    opacity:0.4;
    cursor:not-allowed;
    pointer-events:none;
  }
  .packs-cat-count{font-size:12px;font-weight:600;color:var(--text-muted);}
  /* Per-category icon — admin-set SVG or emoji, rendered at a fixed 16px box so
     the two icon types (and categories with neither) all keep the row's text
     baseline lined up instead of jumping around with glyph size. */
  .packs-cat-label{display:inline-flex;align-items:center;gap:7px;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
  .packs-cat-icon{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;flex-shrink:0;color:currentColor;}
  .packs-cat-icon svg{width:100%;height:100%;display:block;}
  .packs-cat-icon-emoji{font-size:14px;line-height:1;}
  .packs-cat-section-label{
    padding:14px 10px 4px;font-size:11px;font-weight:800;letter-spacing:.06em;
    text-transform:uppercase;color:var(--text-muted);
  }
  /* Sale category — tinted with the same accent as .pack-badge-sale so the
     sidebar entry reads as a sale at a glance, not as another plain category */
  .packs-cat-sale{color:#2563eb;font-weight:700;}
  .packs-cat-sale:hover{color:#1d4ed8;background:rgba(37,99,235,.07);}
  .packs-cat-sale.active{color:#2563eb;background:rgba(37,99,235,.09);}
  .packs-cat-sale .packs-cat-count{color:#2563eb;opacity:.75;}
  body.dark .packs-cat-sale{color:#93c5fd;}
  body.dark .packs-cat-sale:hover{color:#bfdbfe;background:rgba(96,165,250,.1);}
  body.dark .packs-cat-sale.active{color:#93c5fd;background:rgba(96,165,250,.12);}
  body.dark .packs-cat-sale .packs-cat-count{color:#93c5fd;}
  .packs-cat-edit-btn{
    display:none;align-items:center;justify-content:center;
    width:100%;padding:9px 10px;margin-top:8px;border-radius: 12px;
    border:1.5px solid var(--border);background:none;color:var(--text-soft);
    font-family:'Geist','DM Sans',sans-serif;font-size:13px;font-weight:700;cursor:pointer;transition:all .15s;
    box-sizing:border-box;
  }
  .packs-cat-edit-btn:hover{background:rgba(0,0,0,0.04);color:var(--text);border-color:var(--text-muted);}
  body.dark .packs-cat-edit-btn:hover{background:rgba(255,255,255,0.05);}
  .packs-cat-edit-btn.active{color:var(--text);font-weight:800;background:rgba(0,0,0,0.04);border-color:var(--text-muted);}
  body.dark .packs-cat-edit-btn.active{background:rgba(255,255,255,0.06);}

  /* ── Pack Builder promo card — same family as builder.html's sidebar promo,
     pointing the other direction (Browse → Pack Builder). ── */
  .packs-promo-card{
    margin-top:20px;background:#F3EAFD;border:1.5px solid rgba(124,58,237,0.12);
    border-radius: 16px;padding:22px 20px;position:relative;overflow:hidden;
    display:flex;align-items:center;justify-content:space-between;
    box-shadow:0 2px 12px rgba(124,58,237,0.04);user-select:none;
  }
  body.dark .packs-promo-card{background:rgba(124,58,237,0.14);border-color:rgba(167,139,250,0.22);}
  .packs-promo-card-content{flex:1;min-width:0;padding-right:6px;z-index:1;}
  .packs-promo-card-title{
    font-family:'Inter','Geist','Fredoka',sans-serif;font-size:16px;font-weight:800;
    color:#4C1D95;margin:0 0 8px;line-height:1.25;letter-spacing:-0.015em;
  }
  body.dark .packs-promo-card-title{color:#DDD6FE;}
  .packs-promo-card-sub{
    font-family:'Inter','Geist',sans-serif;font-size:13.5px;font-weight:600;
    color:#4C1D95;margin:0 0 14px;line-height:1.55;letter-spacing:-0.01em;
  }
  body.dark .packs-promo-card-sub{color:#DDD6FE;}
  .packs-promo-card-sparkles{flex-shrink:0;display:flex;align-items:center;justify-content:center;pointer-events:none;z-index:1;}
  .packs-promo-card-btn{
    display:inline-flex;align-items:center;gap:7px;width:100%;justify-content:center;
    padding:10px 16px;border:none;border-radius:12px;background:#7C3AED;color:#fff;
    font-family:'Geist','DM Sans',sans-serif;font-size:13.5px;font-weight:700;
    cursor:pointer;text-decoration:none;box-sizing:border-box;transition:background .15s;
  }
  .packs-promo-card-btn:hover{background:#6D28D9;}
  .packs-cat-add-btn{
    display:none;align-items:center;justify-content:center;gap:6px;
    width:100%;padding:10px;margin-top:10px;border-radius: 12px;
    border:1.5px dashed var(--border);background:none;color:var(--text-soft);
    font-family:'Geist','DM Sans',sans-serif;font-size:13px;font-weight:700;cursor:pointer;transition:all .15s;
    box-sizing:border-box;
  }
  .packs-cat-add-btn:hover{background:rgba(0,0,0,0.04);color:var(--text);border-color:var(--text-muted);}
  body.dark .packs-cat-add-btn:hover{background:rgba(255,255,255,0.05);}
  .packs-cat-clear-zone {
    display:none;align-items:center;justify-content:center;gap:8px;
    width:100%;padding:10px;margin-top:10px;border-radius:8px;
    border:1.5px dashed var(--border);background:none;color:var(--text-muted);
    font-family:'Geist','DM Sans',sans-serif;font-size:13px;font-weight:700;
    cursor:pointer;transition:all 0.15s;box-sizing:border-box;
  }
  .packs-cat-clear-zone.active-target {
    border-color:#EF4444;color:#EF4444;
  }
  .packs-cat-clear-zone.drag-over {
    background:rgba(239, 68, 68, 0.1);border-color:#EF4444;transform:scale(1.02);color:#EF4444;
  }
  .packs-cat-delete-x {
    display:flex;align-items:center;justify-content:center;
    width:20px;height:20px;border:none;background:none;
    border-radius:4px;color:#EF4444;font-size:16px;font-weight:700;
    cursor:pointer;transition:all 0.15s;margin-left:2px;
  }
  .packs-cat-delete-x:hover {
    background:rgba(239, 68, 68, 0.1);color:#DC2626;
  }
  .packs-cat-rename-btn {
    display:flex;align-items:center;justify-content:center;
    width:20px;height:20px;border:none;background:none;
    border-radius: 12px;color:var(--text-muted);
    cursor:pointer;transition:all 0.15s;margin-left:2px;flex-shrink:0;
  }
  .packs-cat-rename-btn:hover {
    background:rgba(124,58,237,0.1);color:#7C3AED;
  }
  .packs-cat-item-row{display:flex;align-items:center;gap:2px;}
  .packs-cat-item-row .packs-cat-item{flex:1;min-width:0;}
  .packs-cat-reorder{display:flex;flex-direction:column;gap:1px;flex-shrink:0;}
  .packs-cat-reorder-btn{
    width:18px;height:14px;border:none;background:none;color:var(--text-muted);
    cursor:pointer;display:flex;align-items:center;justify-content:center;padding:0;
    font-size:8px;border-radius: 12px;transition:all .15s;
  }
  .packs-cat-reorder-btn:hover{background:rgba(0,0,0,0.06);color:var(--text);}
  .packs-cat-reorder-btn:disabled{opacity:.3;cursor:default;pointer-events:none;}
  .packs-cat-item.drag-over{background:rgba(var(--pp-green-600-rgb), 0.12);color:var(--pp-green-600);}
  .packs-cat-sortable{position:relative;border-radius:9px;transition:opacity .15s,background .15s;}
  .packs-cat-drag-handle{
    width:25px;height:34px;flex:0 0 25px;padding:0;border:0;border-radius:7px;
    display:flex;align-items:center;justify-content:center;background:transparent;
    color:var(--text-muted);cursor:grab;touch-action:none;
  }
  .packs-cat-drag-handle:hover{color:var(--pp-green-600);background:rgba(var(--pp-green-600-rgb), .08);}
  .packs-cat-drag-handle:active{cursor:grabbing;}
  .packs-cat-drag-handle:focus-visible{outline:2px solid var(--pp-green-600);outline-offset:1px;}
  .packs-cat-sortable.is-category-dragging{opacity:.42;}
  .packs-cat-sortable.category-drag-before::before,
  .packs-cat-sortable.category-drag-after::after{
    content:"";position:absolute;z-index:4;left:2px;right:2px;height:3px;
    border-radius:3px;background:var(--pp-green-600);box-shadow:0 0 0 2px rgba(var(--pp-green-600-rgb), .14);
  }
  .packs-cat-sortable.category-drag-before::before{top:-2px;}
  .packs-cat-sortable.category-drag-after::after{bottom:-2px;}
  body.dark .packs-cat-drag-handle:hover{color:var(--pp-green-400);background:rgba(var(--pp-green-400-rgb), .1);}

  /* Content header — Sticky top bar with scroll mask */
  .packs-content-header{
    display:flex;align-items:center;justify-content:space-between;
    margin-bottom:20px;position:sticky;top:72px;z-index:25;
    background:var(--bg);padding:14px 0;
    border-bottom:1px solid var(--border);
  }
  /* Small scroll-seam mask, not a full 72px block — a 72px-tall reach here
     ends up painting a solid rectangle over the overwrite-mode banner (and
     anything else sitting just above this header) even before the page has
     scrolled far enough for the header to actually be stuck, since CSS has
     no way to condition this pseudo-element on "currently stuck". Keeping
     the reach small means it can only ever cover the few pixels right at
     this header's own top edge, never content further up the page. */
  .packs-content-header::before{
    content:'';position:absolute;top:-10px;left:-20px;right:-20px;
    height:10px;background:var(--bg);pointer-events:none;
  }
  .packs-content-title{
    font-size:22px;font-weight:700;color:var(--text);margin:0;
    font-family:'Geist','DM Sans',sans-serif;
  }
  .packs-content-heading{display:flex;align-items:center;gap:10px;min-width:0;}
  /* The smaller count's cap-height made it look slightly high beside the
     category name even though the flex boxes were mathematically centered. */
  .packs-content-heading .packs-count-pill{transform:translateY(2px);}

  /* ── Mobile category sheet ──
     Desktop keeps the vertical sidebar; ≤1024px the *same* aside becomes a
     slide-up sheet driven by these three pieces. All three are inert above the
     breakpoint so the desktop layout is untouched. */
  .packs-cat-mobile-btn{display:none;}
  .packs-cat-sheet-backdrop{display:none;}
  .packs-sort-sheet-backdrop{display:none;}
  .packs-sheet-head{display:none;}
  .packs-sort-sheet-head{display:none;}
  .packs-cat-label-sheet{display:none;}

  @media(max-width:1024px){
    /* align-items on .packs-layout is flex-start, which on the desktop ROW axis
       means "don't stretch the columns to equal height". Flipping to a column
       makes that same value apply to WIDTH — so each child shrank to its
       max-content width instead of the container's, and .packs-content ended up
       521px wide inside a 343px phone viewport, scrolling the whole page
       sideways by ~180px. Stretch is what's wanted once the axis flips. */
    .packs-layout{flex-direction:column;gap:16px;align-items:stretch;}
    .packs-content{width:100%;min-width:0;}
    /* The control row (search, view toggle, sort) is ~490px of nowrap content;
       let it wrap rather than set the width floor for the whole column. On a
       phone it also drops onto its own line under the title — min-width:auto is
       the flex default and would otherwise stop it shrinking to fit beside one. */
    .packs-content-header{flex-wrap:wrap;gap:10px;}
    .packs-header-controls{flex-wrap:wrap;min-width:0;flex:1 1 100%;gap:8px !important;}
    /* The category control may scroll away or be visually reduced to an icon,
       so keep a compact, persistent selected-category label with the count. */
    .packs-content-heading{flex:1 1 100%;width:100%;min-width:0;}
    .packs-content-heading .packs-content-title{
      display:block;min-width:0;overflow:hidden;text-overflow:ellipsis;
      white-space:nowrap;font-size:18px;
    }
    .packs-content-heading .packs-count-pill{flex-shrink:0;}
    /* Search on its own row, then the two filter controls share the next one.
       The 340px inline width on .packs-search-inner is a desktop sizing hint;
       flex-basis:100% overrides it as the main size, but zero it out anyway so
       nothing downstream reads a 340px floor on a 343px viewport. */
    .packs-search-inner{flex:1 1 100% !important;width:auto !important;min-width:0;}
    .packs-cat-mobile-btn,.packs-view-wrap{flex:1 1 0;min-width:0;}
    .packs-view-btn{width:100%;min-width:0;}
    .packs-view-dropdown{width:100%;left:0 !important;right:0 !important;}

    /* Trigger: mirrors .packs-view-btn's shape so the two read as one pair */
    .packs-cat-mobile-btn{
      display:flex;align-items:center;gap:8px;
      height:38px;padding:0 10px 0 12px;
      border:1.5px solid var(--border);border-radius:12px;background:var(--white);
      font-family:'DM Sans',sans-serif;font-size:13px;font-weight:700;color:var(--text);
      cursor:pointer;transition:border-color .15s;
    }
    body.dark .packs-cat-mobile-btn{background:#141416;border-color:#26262B;color:#F2F2F0;}
    .packs-cat-mobile-btn.open{border-color:var(--pp-green-600);}
    .packs-cat-mobile-ico{display:flex;flex-shrink:0;color:var(--text-soft);}
    /* Long category names truncate rather than widening the button past its
       half of the row and pushing Sort off the edge. */
    .packs-cat-mobile-label{
      flex:1;min-width:0;text-align:left;
      overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
    }
    .packs-cat-mobile-chev{flex-shrink:0;color:var(--text-soft);}

    /* Backdrop. .page-wrap sets z-index:1, which caps everything inside it
       below the fixed site header (z-index:999) — so the body class lifts
       .page-wrap for as long as the sheet is open, same trick builder.css
       uses for its pack sheet. */
    body.pp-cat-sheet-open .page-wrap{z-index:1080;}
    .packs-cat-sheet-backdrop{
      display:block;position:fixed;inset:0;z-index:1070;
      background:rgba(10,8,20,.45);
      backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px);
      opacity:0;pointer-events:none;transition:opacity .25s ease;
    }
    .packs-cat-sheet-backdrop.show{opacity:1;pointer-events:auto;}

    /* Sort uses the same mobile bottom-sheet surface as Category. Desktop
       keeps the anchored popover above; only this breakpoint changes its
       placement, palette and touch targets. */
    body.pp-sort-sheet-open .page-wrap{z-index:1080;}
    .packs-sort-sheet-backdrop{
      display:block;position:fixed;inset:0;z-index:1070;
      background:rgba(10,8,20,.45);
      backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px);
      opacity:0;pointer-events:none;transition:opacity .25s ease;
    }
    .packs-sort-sheet-backdrop.show{opacity:1;pointer-events:auto;}
    #packsSortDd.packs-view-dropdown{
      display:flex;
      position:fixed;left:0 !important;right:0 !important;bottom:0;top:auto;
      width:100%;min-width:0;max-height:min(76vh,600px);z-index:1075;
      flex-direction:column;gap:2px;align-items:stretch;
      background:var(--white);border:none;border-radius:20px 20px 0 0;
      padding:0 12px calc(14px + env(safe-area-inset-bottom,0px));
      box-shadow:0 -10px 44px rgba(0,0,0,.28);
      overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;
      transform:translateY(101%);visibility:hidden;
      transition:transform .3s cubic-bezier(.4,0,.2,1),visibility 0s .3s;
    }
    body.dark #packsSortDd.packs-view-dropdown{background:#16161A;}
    #packsSortDd.packs-view-dropdown.open{
      transform:translateY(0);visibility:visible;
      transition:transform .3s cubic-bezier(.4,0,.2,1),visibility 0s 0s;
    }
    .packs-sort-sheet-head{
      display:flex;align-items:center;justify-content:space-between;
      position:sticky;top:0;z-index:2;flex-shrink:0;
      margin:0 -12px;padding:20px 16px 10px;background:var(--white);
    }
    body.dark .packs-sort-sheet-head{background:#16161A;}
    .packs-sort-sheet-head::before{
      content:'';position:absolute;top:8px;left:50%;transform:translateX(-50%);
      width:42px;height:4px;border-radius:16px;background:var(--border);
    }
    #packsSortDd .packs-view-opt{
      width:100%;min-height:44px;padding:12px 10px;border-radius:10px;
      color:var(--text-soft);font-size:15px;font-weight:500;
    }
    #packsSortDd .packs-view-opt:hover{background:rgba(0,0,0,.05);}
    #packsSortDd .packs-view-opt.active{
      background:rgba(0,0,0,.05);color:var(--text);font-weight:800;
    }
    body.dark #packsSortDd .packs-view-opt{color:var(--text-soft);}
    body.dark #packsSortDd .packs-view-opt:hover,
    body.dark #packsSortDd .packs-view-opt.active{
      background:rgba(255,255,255,.07);color:var(--text);
    }

    /* The sidebar itself, restyled as the sheet */
    .packs-sidebar{
      position:fixed;left:0;right:0;bottom:0;top:auto;
      width:100%;max-height:min(76vh,600px);
      z-index:1075;
      display:flex;flex-direction:column;gap:2px;align-items:stretch;
      background:var(--white);border-right:none;
      border-radius:20px 20px 0 0;
      padding:0 12px calc(14px + env(safe-area-inset-bottom,0px));
      box-shadow:0 -10px 44px rgba(0,0,0,.28);
      overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;
      scrollbar-width:none;-ms-overflow-style:none;
      transform:translateY(101%);
      transition:transform .3s cubic-bezier(.4,0,.2,1),visibility 0s .3s;
      visibility:hidden;
    }
    body.dark .packs-sidebar{background:#16161A;}
    .packs-sidebar::-webkit-scrollbar{display:none;}
    .packs-sidebar.open{
      transform:translateY(0);visibility:visible;
      transition:transform .3s cubic-bezier(.4,0,.2,1),visibility 0s 0s;
    }
    @media (prefers-reduced-motion: reduce){
      .packs-sidebar{transition:none;}
      .packs-cat-sheet-backdrop,.packs-sort-sheet-backdrop,
      #packsSortDd.packs-view-dropdown{transition:none;}
    }
    .packs-sidebar-indicator{display:none;}

    /* Sheet header — sticks while the category list scrolls under it */
    .packs-sheet-head{
      display:flex;align-items:center;justify-content:space-between;
      position:sticky;top:0;z-index:2;flex-shrink:0;
      margin:0 -12px;padding:20px 16px 10px;
      background:var(--white);
    }
    body.dark .packs-sheet-head{background:#16161A;}
    /* Grab handle, drawn on the head so it stays put while the list scrolls */
    .packs-sheet-head::before{
      content:'';position:absolute;top:8px;left:50%;transform:translateX(-50%);
      width:42px;height:4px;border-radius: 16px;background:var(--border);
    }
    .packs-sheet-title{
      font-family:'Geist','DM Sans',sans-serif;font-size:16px;font-weight:800;
      color:var(--text);letter-spacing:-0.01em;
    }
    .packs-sheet-close{
      display:flex;align-items:center;justify-content:center;
      width:30px;height:30px;flex-shrink:0;margin-right:-4px;
      border:none;border-radius:50%;background:rgba(0,0,0,.05);
      color:var(--text-soft);font-size:14px;line-height:1;cursor:pointer;
    }
    body.dark .packs-sheet-close{background:rgba(255,255,255,.07);}

    /* Grouping labels — the whole point of the sheet over the old chip strip:
       "Your Packs" / "Offers" / "Categories" are three different kinds of
       filter and used to sit shoulder-to-shoulder in one undifferentiated row. */
    .packs-cat-label-sheet{display:block;}
    .packs-cat-section-label{padding:12px 6px 2px;}
    /* Full-width rows with a 44px touch target, not pills */
    .packs-cat-item{
      width:100%;flex-shrink:0;
      padding:12px 10px;border:none;border-radius:10px;
      font-size:15px;
    }
    .packs-cat-item.active{
      background:rgba(0,0,0,.05);font-weight:800;
    }
    body.dark .packs-cat-item.active{background:rgba(255,255,255,.07);}
    /* Checkmark removed on active row */
    .packs-cat-item.active::after{display:none !important;}
    /* margin-left:auto keeps the count pinned right once the active row grows a
       third child (the ::after checkmark) and space-between stops sufficing. */
    .packs-cat-count{font-size:13px;margin-left:auto;}
    /* Admin-only controls keep their shape in the sheet */
    .packs-cat-add-btn,.packs-cat-edit-btn,.packs-cat-back-btn{flex-shrink:0;white-space:nowrap;}
    /* The scroll-seam mask bleeds 20px past each edge to cover the desktop
       gutter. `.page` only has 16px of padding here, so the extra 4px hung off
       the right of the viewport and gave the whole page a horizontal scroll.
       Match the bleed to the actual mobile gutter. */
    .packs-content-header::before{left:-16px;right:-16px;}
    /* Dynamic categories render into #packsCatList; it must not introduce a
       block of its own between the sheet's flex rows. */
    #packsCatList{display:contents;}
  }

  /* Small phones: the Pack Builder's control row shape. Both controls used to
     collapse to 40px icon chips, which left the row two small squares on the
     left and a wide strip of nothing beside them — and the category, the one
     thing worth reading here, lost its label. The category trigger keeps its
     label and takes the whole remaining width; only the sort button becomes an
     icon square beside it (it gains a dedicated glyph because the chevron alone
     wouldn't read as "sort" without its label). Same tap targets, same
     handlers. */
  @media(max-width:480px){
    .packs-cat-mobile-btn{
      flex:1 1 auto !important;width:auto;min-width:0;height:38px;
    }
    .packs-view-wrap{flex:0 0 auto !important;}
    .packs-view-btn{
      flex:0 0 auto !important;width:44px;min-width:44px;height:38px;
      padding:0 !important;justify-content:center;gap:0 !important;
    }
    #packsSortVal,.packs-sort-chev{display:none !important;}
    .packs-sort-ico{display:flex;}
    /* Harmless with the fixed bottom sheet above, kept explicit. */
    #packsSortDd.packs-view-dropdown{width:100%;}
  }

  /* .packs-content-header's top:72px is sized for the 64px desktop bar — its
     10px ::before mask covers the leftover 8px seam. The mobile bar is 58px,
     so that same offset opened a 14px slot the mask can't reach, and a sliver
     of the scrolling card grid showed through between the header and this bar.
     Pin it to the real bar height instead; with the announce banner up the
     fixed stack is 38px taller. 999.98px, not the 1024px the rest of the
     mobile packs layout uses, because the header only drops to 58px below
     1000px — and this block must stay after the 1024px one above so the
     equal-specificity top wins. */
  @media(max-width:999.98px){
    .packs-content-header{top:58px;}
    body.sh-has-announce .packs-content-header{top:96px;}
  }

  /* Pack card — no card chrome, just a floating rounded image + text underneath */
  .pack-card{
    background:none;border:none;border-radius:0;box-shadow:none;
    padding:0;display:flex;flex-direction:column;gap:0;overflow:visible;
    transition:transform .2s ease,opacity .15s ease;position:relative;cursor:pointer;
  }
  .pack-card:hover{transform:translateY(-2px);}

  /* A real anchor stretched over the whole card.
     The card cannot itself be an <a> — it contains its own buttons (admin edit
     controls, "Overwrite this pack") and anchors may not nest interactive
     children — so the link is a sibling overlay instead of a wrapper. This is
     what gives the grid right-click → "Open link in new tab", middle-click,
     Ctrl+click, "Copy link address", a URL on hover, and a crawlable link to
     every pack page. A <div onclick> could offer none of those.
     z-index 1 deliberately sits under .pack-card-edit-controls (z-index 10). */
  .pack-card-link{
    position:absolute;inset:0;z-index:1;
    border-radius:inherit;text-decoration:none;color:inherit;
  }
  /* Inert while reordering: anchors drag themselves by default, which would
     fight the card's own drag. The card keeps onclick/role in that mode. */
  .pack-card[draggable="true"] .pack-card-link{pointer-events:none;}
  /* Anything meant to be clicked INSTEAD of the card has to clear the overlay.
     The edit controls already carry z-index 10; the footer is in normal flow
     and needs promoting, or "Overwrite this pack" becomes unclickable. */
  .pack-card-footer{position:relative;z-index:2;}

  /* The anchor is the focusable element now, so the ring belongs on it. Offset
     clears the hero image, which scales past the card's own box. */
  .pack-card-link:focus-visible{
    outline:3px solid var(--accent,var(--pp-green-600));
    outline-offset:4px;
    border-radius:12px;
  }
  body.dark .pack-card-link:focus-visible{outline-color:var(--pp-green-400);}

  /* Reorder mode only: there the card itself is focusable (role="link"
     tabindex="0") because the overlay is inert, so it needs its own ring or
     tabbing through the grid is invisible movement. */
  .pack-card:focus-visible{
    outline:3px solid var(--accent,var(--pp-green-600));
    outline-offset:4px;
    border-radius:12px;
    transform:translateY(-2px);
  }
  body.dark .pack-card:focus-visible{outline-color:var(--pp-green-400);}
  .pack-card[draggable="true"],
  .pack-card[draggable="true"] *{cursor:grab;}
  .pack-card[draggable="true"]:active,
  .pack-card[draggable="true"]:active *{cursor:grabbing;}
  .packs-grid.pack-order-active::before{
    content:"Drag a pack, then drop on the left or right half of another pack.";
    grid-column:1 / -1;
    padding:10px 12px;border:1px dashed rgba(var(--pp-green-600-rgb), .42);border-radius:9px;
    background:rgba(var(--pp-green-600-rgb), .07);color:var(--pp-green-700);
    font:700 12px/1.35 'Geist','DM Sans',sans-serif;
  }
  body.dark .packs-grid.pack-order-active::before{color:var(--pp-green-400);background:rgba(var(--pp-green-400-rgb), .08);border-color:rgba(var(--pp-green-400-rgb), .35);}
  body.pack-order-mode .packs-header-controls{opacity:.45;pointer-events:none;}
  .pack-card.pack-is-dragging{opacity:.35;transform:scale(.97);}
  .packs-grid.pack-order-active .pack-card:hover{transform:none;}
  .packs-grid.pack-order-active .pack-card:hover .pack-card-hero{opacity:1;transform:scale(1.35);}
  .pack-card.pack-drop-before::before,
  .pack-card.pack-drop-after::after{
    content:"";position:absolute;z-index:30;top:0;bottom:0;width:4px;
    border-radius:999px;background:var(--pp-green-500);
    box-shadow:0 0 0 3px rgba(var(--pp-green-500-rgb), .18),0 0 18px rgba(var(--pp-green-500-rgb), .45);
    pointer-events:none;
  }
  .pack-card.pack-drop-before::before{left:-9px;}
  .pack-card.pack-drop-after::after{right:-9px;}
  .pack-card-hero{
    width:100%;aspect-ratio:1/1;object-fit:cover;
    border-radius: 16px;cursor:pointer;display:block;background:var(--bg);
    transition:opacity .15s, transform .25s ease;
    transform:scale(1.35);
  }
  .pack-card:hover .pack-card-hero{opacity:.92;transform:scale(1.37);}


  /* Corner badge row — draft/new/sale pills sit top-left on the card image,
     side by side so a pack that's e.g. both new and on sale shows both
     at once instead of one overwriting the other. */
  .pack-card-badges{position:absolute;top:10px;left:12px;z-index:10;display:flex;flex-direction:row;flex-wrap:wrap;align-items:flex-start;gap:6px;}
  .pack-badge-draft,.pack-badge-sale,.pack-badge-soon{
    padding:6px 9px;border-radius:50px;font-size:10.5px;font-weight:900;letter-spacing:.05em;
    color:#fff;box-shadow:0 2px 6px rgba(0,0,0,.2);white-space:nowrap;
  }
  .pack-badge-draft{background:rgba(217,119,6,0.85);backdrop-filter:blur(4px);}
  .pack-badge-ghost{background:rgba(var(--pp-green-700-rgb), .92);backdrop-filter:blur(4px);}
  .pack-badge-soon{background:rgba(180,83,9,.92);backdrop-filter:blur(4px);}
  .pack-badge-hidden{background:rgba(63,63,70,.95);backdrop-filter:blur(4px);}
  /* Admin-only: a listing no customer can see. Greyed, not removed, so it can
     still be opened and edited. Badges and edit controls stay full strength. */
  .pack-card-hidden .pack-card-hero,
  .pack-card-hidden > :not(.pack-card-img):not(.pack-card-link):not(.pack-card-edit-controls):not(.pack-card-copy){filter:grayscale(1);opacity:.45;}
  .pack-card-hidden:hover .pack-card-hero,
  .pack-card-hidden:hover > :not(.pack-card-img):not(.pack-card-link):not(.pack-card-edit-controls):not(.pack-card-copy){opacity:.75;}
  /* Admin-only "Copy link" on a customer-bound ghost listing (copyCustomLink). */
  .pack-card-copy{
    position:relative;z-index:2;margin-top:10px;width:100%;
    display:flex;align-items:center;justify-content:center;gap:6px;
    padding:8px 10px;border-radius:12px;cursor:pointer;
    border:1.5px solid rgba(var(--pp-green-600-rgb), .35);background:rgba(var(--pp-green-600-rgb), .08);
    color:var(--pp-green-700);font-family:'Geist','DM Sans',sans-serif;font-size:12.5px;font-weight:700;
    transition:background .15s,border-color .15s;
  }
  .pack-card-copy span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
  .pack-card-copy:hover{background:rgba(var(--pp-green-600-rgb), .16);border-color:rgba(var(--pp-green-600-rgb), .55);}
  body.dark .pack-card-copy{color:var(--pp-green-400);border-color:rgba(var(--pp-green-400-rgb), .35);background:rgba(var(--pp-green-400-rgb), .08);}
  body.dark .pack-card-copy:hover{background:rgba(var(--pp-green-400-rgb), .16);border-color:rgba(var(--pp-green-400-rgb), .55);}
  .packs-cat-custom{color:var(--pp-green-700);font-weight:700;}
  body.dark .packs-cat-custom{color:var(--pp-green-400);}
  .packs-ghost-btn{border-color:rgba(var(--pp-green-600-rgb), .25);color:var(--pp-green-700);}
  body.dark .packs-ghost-btn{color:var(--pp-green-400);border-color:rgba(var(--pp-green-400-rgb), .28);}

  #ghostListingModal{
    z-index:10050;
    background:rgba(15,15,17,.62);
    backdrop-filter:blur(5px);-webkit-backdrop-filter:blur(5px);
  }
  .ghost-listing-modal{
    max-width:560px;padding:28px;border:1px solid var(--border);border-radius:16px;
    background:var(--white);font-family:'Geist','DM Sans',sans-serif;
    box-shadow:0 24px 64px rgba(15,15,17,.22),0 6px 18px rgba(15,15,17,.1);
  }
  .ghost-listing-modal .modal-title{
    margin-bottom:6px;padding-right:44px;color:var(--text);
    font-family:'Geist','DM Sans',sans-serif;font-size:23px;font-weight:800;
    line-height:1.18;letter-spacing:-.025em;
  }
  .ghost-listing-modal .modal-sub{
    margin-bottom:24px;color:var(--text-soft);font-size:13.5px;font-weight:500;line-height:1.42;
  }
  .ghost-listing-modal .modal-close{
    top:16px;right:16px;width:34px;height:34px;padding:0;border:0;border-radius:9px;
    background:transparent;color:var(--text-muted);font-size:0;
    transition:color .15s,background .15s;
  }
  .ghost-listing-modal .modal-close:hover{
    background:color-mix(in srgb,var(--text) 7%,transparent);color:var(--text);transform:none;
  }
  .ghost-listing-modal .modal-close:focus-visible{outline:2px solid var(--accent);outline-offset:2px;}
  .ghost-listing-kicker{display:inline-flex;align-items:center;gap:7px;margin-bottom:10px;color:var(--pp-green-700);font-size:11px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;}
  .ghost-image-field{position:relative;margin-top:20px;}
  .ghost-image-label{margin-bottom:7px;font-size:11px;font-weight:800;letter-spacing:.05em;text-transform:uppercase;color:var(--text-muted);}
  .ghost-image-picker{
    position:relative;width:100%;height:148px;padding:0;overflow:hidden;
    border:1.5px dashed var(--border);border-radius:10px;background:var(--bg);
    color:var(--text-muted);cursor:pointer;outline:none;transition:border-color .15s,background .15s,box-shadow .15s;
    /* A <button> does not inherit font-family, so without this the label and
       hint below render in the UA default (Arial) next to the Inter/Geist text
       of every sibling field in the modal. */
    font-family:inherit;
  }
  .ghost-image-picker:hover{border-color:var(--pp-green-600);background:rgba(var(--pp-green-600-rgb), .035);}
  .ghost-image-picker:focus-visible{border-color:var(--pp-green-600);box-shadow:0 0 0 3px rgba(var(--pp-green-600-rgb), .12);}
  .ghost-image-picker.is-uploading{cursor:wait;opacity:.68;}
  .ghost-image-picker.has-error{border-color:#ef4444;box-shadow:0 0 0 3px rgba(239,68,68,.1);}
  .ghost-image-empty{height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px;pointer-events:none;}
  .ghost-image-empty svg{margin-bottom:2px;color:var(--pp-green-600);}
  .ghost-image-empty strong{font-size:13px;color:var(--text);}
  .ghost-image-empty small{font-size:10.5px;font-weight:600;}
  #ghostListingImagePreview{width:100%;height:100%;object-fit:cover;display:block;}
  .ghost-image-change{position:absolute;left:50%;bottom:10px;transform:translateX(-50%);padding:6px 10px;border-radius:7px;background:rgba(10,10,12,.76);color:#fff;font-size:10px;font-weight:800;backdrop-filter:blur(6px);pointer-events:none;white-space:nowrap;}
  .ghost-image-remove{position:absolute;z-index:3;top:27px;right:8px;width:31px;height:31px;padding:0;border:1px solid rgba(255,255,255,.16);border-radius:8px;background:rgba(10,10,12,.74);color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;backdrop-filter:blur(6px);}
  .ghost-image-remove:hover{background:#dc2626;}
  .ghost-image-status{min-height:16px;margin-top:6px;font-size:11px;font-weight:650;color:var(--text-muted);}
  .ghost-image-status.success{color:var(--pp-green-700);}
  .ghost-image-status.error{color:#dc2626;}
  .ghost-listing-fields{display:grid;grid-template-columns:1fr 160px;gap:14px;margin-top:20px;}
  .ghost-field{display:flex;flex-direction:column;gap:7px;min-width:0;}
  .ghost-field-wide{grid-column:1 / -1;}
  .ghost-field>span{font-size:11px;font-weight:800;letter-spacing:.05em;text-transform:uppercase;color:var(--text-muted);}
  .ghost-field em{font-style:normal;font-weight:600;text-transform:none;letter-spacing:0;}
  .ghost-field input,.ghost-field textarea,.ghost-field select{width:100%;box-sizing:border-box;border:1px solid var(--border);border-radius:9px;background:var(--bg);color:var(--text);padding:11px 12px;font:600 14px 'Geist','DM Sans',sans-serif;outline:none;transition:border-color .15s,box-shadow .15s;}
  .ghost-field select{cursor:pointer;appearance:auto;}
  .ghost-field textarea{resize:vertical;min-height:86px;line-height:1.45;}
  .ghost-field input:focus,.ghost-field textarea:focus,.ghost-field select:focus{border-color:var(--pp-green-600);box-shadow:0 0 0 3px rgba(var(--pp-green-600-rgb), .12);}
  .ghost-image-picker [hidden],.ghost-image-field>[hidden]{display:none!important;}
  .ghost-visibility-row{display:flex;align-items:center;justify-content:space-between;gap:18px;margin-top:16px;padding:13px 14px;border:1px solid var(--border);border-radius:10px;background:var(--bg);}
  .ghost-visibility-copy{display:flex;flex-direction:column;gap:3px;min-width:0;}
  .ghost-visibility-copy strong{color:var(--text);font-size:13px;font-weight:800;}
  .ghost-visibility-copy span{color:var(--text-muted);font-size:11px;font-weight:600;line-height:1.35;}
  .ghost-visibility-switch{position:relative;width:38px;height:22px;flex:0 0 38px;cursor:pointer;}
  .ghost-visibility-switch input{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none;}
  .ghost-visibility-slider{position:absolute;inset:0;border:1px solid var(--border);border-radius:999px;background:#3f3f46;transition:background .18s,border-color .18s;}
  .ghost-visibility-slider::after{content:"";position:absolute;top:3px;left:3px;width:14px;height:14px;border-radius:50%;background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.28);transition:transform .18s;}
  .ghost-visibility-switch input:checked + .ghost-visibility-slider{border-color:var(--pp-green-600);background:var(--pp-green-600);}
  .ghost-visibility-switch input:checked + .ghost-visibility-slider::after{transform:translateX(16px);}
  .ghost-visibility-switch input:focus-visible + .ghost-visibility-slider{outline:2px solid var(--pp-green-600);outline-offset:2px;}
  .ghost-listing-note{margin-top:14px;padding:10px 12px;border-left:3px solid var(--pp-green-600);background:rgba(var(--pp-green-600-rgb), .07);color:var(--text-muted);font-size:12px;line-height:1.45;}
  /* Customer bound but Visible in shop off — a listing nobody can open. */
  .ghost-listing-note.is-warn{border-left-color:#f59e0b;background:rgba(245,158,11,.10);color:#d97706;}
  body.dark .ghost-listing-modal .ghost-listing-note.is-warn{color:#fbbf24;}
  .ghost-field .ghost-owner-search{margin-bottom:2px;}
  .ghost-listing-actions{display:grid;grid-template-columns:1fr 1.4fr;gap:10px;margin-top:20px;}
  .ghost-btn-secondary,.ghost-btn-primary{min-height:44px;border-radius:9px;font:800 13px 'Geist','DM Sans',sans-serif;cursor:pointer;transition:transform .15s,opacity .15s,border-color .15s,background .15s;}
  .ghost-btn-secondary{border:1px solid var(--border);background:var(--bg);color:var(--text);}
  .ghost-btn-secondary:hover{background:var(--border);}
  /* See .btn-primary in styles.css — white on #16a34a is 3.3:1. */
  .ghost-btn-primary{border:1px solid var(--pp-green-700);background:var(--pp-green-700);color:#fff;}
  .ghost-btn-primary:hover{background:var(--pp-green-800);border-color:var(--pp-green-800);transform:translateY(-1px);}
  /* In step with the canonical primary in styles.css: white on #15803D in both themes. */
  body.dark .ghost-btn-primary{border-color:var(--pp-green-700);background:var(--pp-green-700);color:#fff;}
  body.dark .ghost-btn-primary:hover{background:var(--pp-green-800);border-color:var(--pp-green-800);}
  .ghost-btn-primary:disabled{opacity:.55;cursor:wait;transform:none;}
  body.dark .ghost-listing-modal{background:#18181c;border-color:#2c2c31;box-shadow:0 26px 72px rgba(0,0,0,.54);}
  body.dark .ghost-listing-modal .modal-sub{color:#a4a4ad;}
  body.dark .ghost-listing-modal .modal-close{background:transparent;color:#777782;}
  body.dark .ghost-listing-modal .modal-close:hover{background:rgba(255,255,255,.07);color:#f2f2f0;}
  body.dark .ghost-listing-modal .ghost-image-label,
  body.dark .ghost-listing-modal .ghost-field>span,
  body.dark .ghost-listing-modal .ghost-image-empty small,
  body.dark .ghost-listing-modal .ghost-listing-note{color:#7f7f89;}
  body.dark .ghost-listing-kicker{color:var(--pp-green-400);}
  @media(max-width:560px){
    .ghost-listing-modal{padding:24px 18px;border-radius:10px;}
    .ghost-image-picker{height:126px;}
    .ghost-listing-fields{grid-template-columns:1fr;}
    .ghost-field-wide{grid-column:auto;}
    .ghost-listing-actions{grid-template-columns:1fr;}
  }
  .pack-badge-sale{
    background:rgba(37,99,235,0.85);backdrop-filter:blur(4px);
    padding:6px 9px 5px;border-radius:50px;font-size:10.5px;font-weight:900;letter-spacing:.02em;
    color:#fff;box-shadow:0 1px 4px rgba(0,0,0,.15);white-space:nowrap;
    display:inline-flex;align-items:center;justify-content:center;line-height:1;margin-left:2px;
  }

  /* "In basket" badge — bottom-right corner of the card image */
  .pack-badge-basket{
    position:absolute;bottom:10px;right:10px;z-index:10;
    display:inline-flex;align-items:center;gap:4px;
    padding:5px 9px;border-radius:6px;font-size:10px;font-weight:800;letter-spacing:.02em;
    background:var(--pp-green-600);color:#fff;
    box-shadow:0 2px 6px rgba(0,0,0,.25);
    pointer-events:none;
  }
  .pack-badge-basket svg{flex-shrink:0;}

  /* "N bought today" — bottom-LEFT, so it never collides with .pack-badge-basket
     in the opposite corner when a popular pack is also already in the basket. */
  .pack-badge-hot{
    position:absolute;bottom:10px;left:10px;z-index:10;
    display:inline-flex;align-items:center;gap:4px;
    padding:5px 9px;border-radius:6px;font-size:10px;font-weight:800;letter-spacing:.02em;
    background:#B45309;color:#fff;
    box-shadow:0 2px 6px rgba(0,0,0,.25);
    pointer-events:none;max-width:calc(100% - 20px);
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  }
  .pack-badge-hot svg{flex-shrink:0;}
  /* Lighter amber on dark: #B45309 against a dark card reads as brown//muddy
     and loses the "hot" cue entirely. Text goes dark to hold contrast. */
  body.dark .pack-badge-hot{background:#F59E0B;color:#1c1917;}

  /* Image container — clips the zoomed hero image to the rounded corners. */
  .pack-card-img{position:relative;width:100%;flex-shrink:0;border-radius:10px;overflow:hidden;transform:translateZ(0);backface-visibility:hidden;}
  .pack-card-hero-placeholder{
    width:100%;aspect-ratio:1/1;border-radius: 16px;
    background:var(--bg);border:1.5px dashed var(--border);
    display:flex;align-items:center;justify-content:center;
    cursor:pointer;transition:border-color .15s;box-sizing:border-box;
  }
  .pack-card-hero-placeholder:hover{border-color:rgba(124,58,237,.4);}
  body.dark .pack-card-hero-placeholder{background:#0f0f11;}

  /* Card body — sits below the image, no background/border of its own */
  .pack-card-body{padding:10px 2px 0;display:flex;flex-direction:column;flex:1;}

  /* Name, then big bold price stacked underneath */
  .pack-name-price-row{display:flex;flex-direction:column;gap:4px;margin-bottom:4px;}
  /* Two lines, not one: a single nowrap line ellipsised almost every name in
     the catalogue (qty-tier variants like "50 Advanced Bugcatcher's Kit" are
     all long). min-height reserves the same 2-line box on every card whether
     its name takes one line or two, so a short name doesn't leave its card
     shorter than its neighbours — cards stay equal height across rows. */
  .pack-card-name{
    font-family:'DM Sans',sans-serif;font-size:15px;font-weight:600;
    color:var(--text);line-height:1.3;
    display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;
    overflow:hidden;text-overflow:ellipsis;white-space:normal;
    min-height:2.6em;
  }
  .pack-card-price{
    font-family:'DM Sans',sans-serif;font-size:20px;font-weight:800;
    color:var(--text);white-space:nowrap;
    display:inline-flex;align-items:center;gap:6px;flex-wrap:wrap;
  }

  /* Shown instead of a price on packs that link into the Pack Builder. Sized
     down from the 20px price it replaces — it's a destination, not a number,
     and at price weight it read as the loudest thing on the card. */
  .pack-card-browse{
    font-size:13px;font-weight:700;color:var(--text-muted);
    white-space:normal;line-height:1.25;
  }
  .pack-card-browse svg{flex-shrink:0;opacity:.8;}

  .pack-price-original{text-decoration:line-through;color:var(--text-muted);font-size:14px;font-weight:600;margin-right:4px;}
  .pack-price-sale{color:var(--text);font-weight:800;}
  /* Sale row. Deliberately nowrap, unlike the plain .pack-card-price it
     extends: with wrapping on, the pill landed beside the price on some cards
     and under it on others purely because the two price strings were a few
     characters wider, which also left cards in one row at different heights.
     One line, pill flushed right — same spot on every card. */
  .pack-card-price-sale{flex-wrap:nowrap;gap:5px;}
  .pack-card-sale-tag{margin-left:auto;flex-shrink:0;}
  /* Tighter than the plain row's 4px. Three things share this line now, and
     .packs-grid can hand a card as little as 205px (auto-fill minmax(205px,1fr)
     at its narrowest), where the widest pair of prices plus the pill came to
     within a pixel of the space available. */
  .pack-card-price-sale .pack-price-original{margin-right:2px;}
  /* Safety valve for a very long pair of prices on a narrow card: nowrap means
     something has to give, and the struck-through old price is the one number
     here nobody needs in full. It shrinks and ellipses so the sale price and
     the pill stay whole and inside the card, rather than the pill hanging off
     the edge. Nothing in the catalogue is currently wide enough to trigger it. */
  .pack-card-price-sale .pack-price-original{min-width:0;overflow:hidden;text-overflow:ellipsis;}
  .pack-card-price-sale .pack-price-sale{flex-shrink:0;}
  /* Footer actions (card) */
  .pack-card-footer{display:flex;gap:6px;margin-top:auto;padding-top:10px;}
  .pack-card-edit-controls{position:absolute;top:10px;right:12px;z-index:10;display:flex;gap:5px;}
  .pack-edit-btn{
    width:26px;height:26px;border-radius: 12px;border:1px solid rgba(255,255,255,.15);
    background:rgba(0,0,0,.65);backdrop-filter:blur(4px);color:#fff;
    cursor:pointer;transition:background .1s,transform .1s;
    display:flex;align-items:center;justify-content:center;outline:none;
  }
  .pack-edit-btn:hover{background:rgba(0,0,0,.8);}
  .pack-edit-btn:active{transform:scale(.9);}
  .pack-delete-btn{
    width:26px;height:26px;border-radius: 12px;border:1px solid rgba(255,255,255,.15);
    background:rgba(0,0,0,.65);backdrop-filter:blur(4px);color:#fff;
    cursor:pointer;transition:background .1s,transform .1s;
    display:flex;align-items:center;justify-content:center;outline:none;
  }
  .pack-delete-btn:hover{background:#DC2626;}
  .pack-delete-btn:active{transform:scale(.9);}
  .pack-popup-footer{display:none;}

  @media(max-width:640px){
    /* Packs list: 2 compact cards per row on phones (was 1 full-width card, so
       only ~2 packs fit on screen). Scales the card internals down — like the
       tighter product cards in builder.html — while keeping hero, name and price
       legible. Tapping a card opens its own pack.html detail page. */
    /* minmax(0,1fr), not 1fr: a bare `1fr` is minmax(auto,1fr), so a card whose
       content has a wide min-content (the hero image row) drags its own column
       past its share and squeezes the other — 166px + 132px against a 288px
       container, overflowing the page. minmax(0,…) lets both tracks shrink to
       an even split and the card contents clip/wrap inside. */
    .packs-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;}
    .packs-grid > *{min-width:0;}
    .pack-card{border-radius: 16px;}
    .pack-card-body{padding:9px 10px 10px;}
    .pack-name-price-row{gap:5px;margin-bottom:2px;}
    .pack-card-name{font-size:12.5px;line-height:1.2;min-height:2.4em;}
    .pack-card-price{font-size:12.5px;}
    .pack-card-edit-controls{top:8px;right:8px;}
    /* Two cards to a row on phones — both prices and the pill share ~140px of
       card, so the pill shrinks and drops the word "OFF". The struck price
       comes down too: at the desktop 14px it was larger than the sale price
       beside it and it's the number that matters least. */
    .pack-card-price-sale{gap:4px;}
    .pack-price-original{font-size:11px;margin-right:2px;}
    .pack-card-sale-tag{padding:4px 6px 3px;font-size:9px;letter-spacing:0;}
    .pack-card-sale-tag .pack-sale-off{display:none;}
    .pack-card-footer{gap:6px;padding-top:9px;}
  }

  /* Overwrite mode banner */
  .overwrite-banner{
    display:flex;align-items:center;gap:12px;flex-wrap:wrap;
    padding:14px 18px;border-radius:12px;margin-bottom:22px;
    width:fit-content;max-width:100%;
    background:rgba(124,58,237,.07);border:1.5px solid rgba(124,58,237,.2);
    font-family:'Geist','DM Sans',sans-serif;font-size:13px;font-weight:600;color:#7C3AED;
    animation:bannerIn .4s cubic-bezier(.34,1.3,.64,1);
  }
  body.dark .overwrite-banner{background:rgba(167,139,250,.1);border-color:rgba(167,139,250,.25);color:#A78BFA;}
  .overwrite-banner-ico{font-size:18px;flex-shrink:0;}
  .overwrite-banner > span:not(.overwrite-banner-ico){flex:none;}
  .overwrite-banner-cancel{
    margin-left:auto;background:none;border:1.5px solid rgba(124,58,237,.3);cursor:pointer;
    color:#7C3AED;border-radius:8px;padding:5px 12px;font-size:11px;font-weight:800;
    font-family:'Nunito',sans-serif;transition:background .15s;white-space:nowrap;
  }
  .overwrite-banner-cancel:hover{background:rgba(124,58,237,.1);}
  .pack-overwrite-btn{
    flex:1;padding:11px;border-radius: 12px;border:2px solid #7C3AED;
    background:#7C3AED;color:#fff;font-family:'Nunito',sans-serif;
    font-size:13px;font-weight:900;cursor:pointer;transition:all .15s;
    display:flex;align-items:center;justify-content:center;gap:6px;
  }
  .pack-overwrite-btn:hover{background:#6d28d9;border-color:#6d28d9;transform:translateY(-1px);}
  body.dark .pack-overwrite-btn{background:#A78BFA;border-color:#A78BFA;color:#0a0a0c;}
  body.dark .pack-overwrite-btn:hover{background:#9061f9;border-color:#9061f9;}

  /* Empty state */
  .packs-empty{
    display:flex;flex-direction:column;align-items:center;justify-content:center;
    padding:56px 20px;text-align:center;color:var(--text-muted);
    border:1.5px dashed var(--border);border-radius:var(--radius);gap:12px;
    grid-column:1/-1;
  }
  .packs-empty-icon{display:flex;align-items:center;justify-content:center;width:48px;height:48px;color:var(--text-muted);}
  .packs-empty-icon svg{width:44px;height:44px;opacity:0.55;}
  .packs-empty-with-dog{justify-content:flex-start;padding:18px 20px 28px;gap:4px;}
  .packs-empty-icon.packs-empty-dog{width:108px;height:112px;}
  .packs-empty-dog img{display:block;width:100%;height:100%;object-fit:contain;}
  .packs-empty-with-dog .packs-empty-title{transform:translateY(4px);}
  .packs-empty-title{font-size:15px;font-weight:600;color:var(--text-soft);}
  .packs-empty-sub{font-size:13px;font-weight:600;max-width:260px;line-height:1.5;}
  .packs-empty-cta{
    display:inline-flex;align-items:center;gap:6px;padding:10px 20px;
    border-radius: 12px;border:1.5px solid #AFAFAF;background:transparent;color:#6B6B7B;
    font-family:'Nunito',sans-serif;font-size:13px;font-weight:800;
    cursor:pointer;text-decoration:none;transition:all .15s;margin-top:4px;
  }
  .packs-empty-cta:hover{border-color:#888;color:#3D3D3D;}

  /* Toast — card look is shared from styles.css; this file only keeps its
     own entrance animation. Position matches styles.css's bottom-right
     default so the toast lands in the same spot on every page. */
  .toast{ animation:toastUp .35s cubic-bezier(.34,1.3,.64,1); }
  @keyframes toastUp{from{transform:translateY(20px) scale(.9);opacity:0;}to{transform:translateY(0) scale(1);opacity:1;}}
