    /* ==================== PHASE 5: CATEGORY SHOPPING ==================== */

    /* Coming soon placeholder for product types with no Firestore products */
    .product-card-coming-soon {
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: 16px 20px;
      border: 1px dashed var(--slate-300);
      border-radius: 12px;
      opacity: 0.5;
      margin-bottom: 12px;
    }
    .coming-soon-label {
      font-size: 0.875rem;
      font-weight: 600;
      color: var(--slate-700);
    }
    .coming-soon-text {
      font-size: 0.8125rem;
      font-weight: 500;
      color: var(--slate-400);
    }

    .shopping-screen { padding-top: 20px; overscroll-behavior: none; }

    .shopping-header {
      background: var(--white);
      border: 1px solid var(--slate-200);
      border-radius: 16px;
      padding: 20px 24px;
      margin-bottom: 20px;
      text-align: center;
      box-shadow: var(--shadow-sm);
      position: relative;
      overflow: hidden;
    }

    .shopping-header::before {
      content: '';
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      height: 3px;
      background: var(--school-primary, var(--cr-teal));
      border-radius: 16px 16px 0 0;
    }

    .category-dots {
      display: flex;
      align-items: center;
      justify-content: center;
      gap: 6px;
      margin-bottom: 8px;
    }


    .shopping-header h2 {
      font-family: var(--font-serif);
      font-size: 1.5rem;
      font-weight: 600;
      color: var(--slate-900);
      margin-bottom: 2px;
    }

    .shopping-header .item-count {
      font-size: 0.9375rem;
      color: var(--slate-600);
    }

    .category-tagline {
      font-size: 0.8125rem;
      color: var(--slate-500);
      margin-top: 6px;
      line-height: 1.4;
      font-style: italic;
    }

/* Large Product Card - Side-by-Side Layout */
    .product-card-large {
      background: var(--white);
      border: 1px solid var(--slate-200);
      border-radius: 16px;
      overflow: hidden;
      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
      margin-bottom: 14px;
      display: grid;
      grid-template-columns: 140px 1fr;
    }

   .image-carousel {
      position: relative;
      width: 128px;
      height: 163px;
      background: var(--slate-100);
      overflow: hidden;
      cursor: pointer;
      display: flex;
      flex-direction: column;
      border-radius: 8px;
      margin: 6px;
    }

    .image-carousel.alt-slide {
      background: var(--slate-100);
    }

    .carousel-track {
      display: flex;
      flex: 1;
      transition: transform 0.3s ease-out;
    }

    .carousel-slide {
      min-width: 100%;
      height: 100%;
      position: relative;
      display: flex;
      align-items: center;
      justify-content: center;
      padding: 10px;
    }

    .carousel-slide img {
      max-width: 100%;
      max-height: 100%;
      object-fit: contain;
      background: var(--slate-50);
      color: transparent;
    }

    .carousel-slide img::before {
      content: '';
      position: absolute;
      inset: 0;
      background: var(--slate-100);
    }

    .carousel-slide.alt-slide {
      background: var(--slate-100);
    }

    .product-badge {
      position: absolute;
      top: 8px;
      left: 8px;
      padding: 3px 8px;
      border-radius: 12px;
      font-size: 0.625rem;
      font-weight: 600;
      z-index: 5;
    }

    .product-badge.our-pick {
      background: rgba(221, 105, 58, 0.75);
      color: var(--white);
    }

    .product-badge.alt {
      background: var(--slate-200);
      color: var(--slate-600);
    }

    .carousel-dots {
      display: flex;
      justify-content: center;
      gap: 6px;
      padding: 12px 0;
      border-bottom: 1px solid var(--slate-100);
    }

    .carousel-indicators {
      display: flex;
      justify-content: center;
      align-items: center;
      gap: 4px;
      padding: 8px 0;
      background: rgba(255,255,255,0.9);
      border-radius: 0 0 12px 12px;
    }

    .carousel-dot {
      width: 6px;
      height: 6px;
      border-radius: 50%;
      background: rgba(70, 158, 146, 0.3);
      cursor: pointer;
      transition: all 0.2s ease;
      border: none;
      padding: 0;
    }

    .carousel-dot.active {
      background: #469E92;
    }

    .product-options-badge {
      /* Killed per design review 2026-04-11 — the "+N ›" counter is now
         redundant with the "Tap for options" / "+N options" tooltip bar
         that lives along the bottom edge of the image. The badge element
         is still rendered by card-ui.js renderLargeCard / renderSmallCard
         and the .hidden-by-coach-mark suppression logic still toggles, but
         this rule hides every instance. To bring it back: delete this one
         line. */
      display: none;
      position: absolute;
      bottom: 6px;
      right: 6px;
      background: rgba(255, 255, 255, 0.92);
      color: #469E92;
      font-family: var(--font-sans, 'DM Sans', sans-serif);
      font-size: 11px;
      font-weight: 600;
      padding: 4px 8px;
      border-radius: 6px;
      z-index: 2;
    }
    .product-card-small .product-options-badge {
      font-size: 10px;
      padding: 3px 6px;
      bottom: 6px;
      right: 6px;
    }

    /* ─── Card Coach Mark — bottom edge tooltip bar ─── */
    /* Spans the full bottom edge of the image container; the product image
       stays fully visible above it. When this bar is present on a card, the
       .product-options-badge "+N ›" counter is hidden as redundant — see
       .product-options-badge.hidden-by-coach-mark below. */
    .card-coach-mark-large,
    .card-coach-mark-small {
      position: absolute;
      bottom: 0;
      left: 0;
      right: 0;
      background: rgba(44, 42, 38, 0.7);
      color: #fff;
      font-family: 'DM Sans', sans-serif;
      font-size: 10px;
      font-weight: 500;
      padding: 4px 0;
      text-align: center;
      letter-spacing: 0.3px;
      border-radius: 0 0 8px 8px;
      z-index: 2;
      pointer-events: none;
    }

    /* Small card override: thinner bar + smaller font so the bar doesn't
       dominate the smaller thumbnail. Copy is also shorter ("+N options"
       instead of "Tap for options") — see injectCoachMark in card-ui.js. */
    .card-coach-mark-small {
      font-size: 9px;
      padding: 3px 0;
    }

    /* Hidden when a coach mark bar is present on the same card. */
    .product-options-badge.hidden-by-coach-mark { display: none; }

    /* Mobile-only: card-level color row (rendered as a sibling of card-content
       on large cards and of the button on small cards). Hidden on desktop —
       the inline copy inside .card-bottom-row / .small-card-info handles
       desktop. The mobile media query below shows it and hides the inline
       copy. See renderLargeCard / renderSmallCard.
       Selector chains both classes because the mobile element also carries
       the .color-change-row class — without the chain, the later
       `.color-change-row { display: flex }` rule wins on equal specificity
       and the mobile copy leaks onto desktop. */
    .color-change-row.color-change-row-mobile { display: none; }

     .card-content {
      padding: 14px 16px;
      display: flex;
      flex-direction: column;
      min-width: 0;
      overflow: hidden;
    }

/* Product type label — headline on cards (DEC-235) */
    .product-type-label {
      font-size: 0.9375rem;
      font-weight: 600;
      color: var(--slate-900);
      line-height: 1.3;
      margin-bottom: 2px;
    }

    .card-content .product-name {
      font-size: 0.8125rem;
      font-weight: 400;
      color: var(--slate-600);
    }

.small-card-info {
      min-width: 0;
      overflow: hidden;
    }

    .small-card-info .product-type-label {
      font-size: 0.8125rem;
      font-weight: 600;
      color: var(--slate-900);
      margin-bottom: 1px;
      display: block;
    }

    .small-card-info h3 {
      font-size: 0.75rem;
      font-weight: 400;
      color: var(--slate-500);
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }

    .lightbox-info .product-type-label {
      font-size: 1.125rem;
      font-weight: 600;
      color: var(--slate-900);
      margin-bottom: 2px;
      display: block;
    }

    .lightbox-info h3 {
      font-size: 0.9375rem;
      font-weight: 400;
      color: var(--slate-600);
    }

    .card-row-top {
      display: flex;
      justify-content: space-between;
      align-items: flex-start;
      gap: 8px;
      margin-bottom: 2px;
    }

    .product-name {
      font-size: 0.9375rem;
      font-weight: 600;
      color: var(--slate-900);
      line-height: 1.3;
    }

    .requirement-badge {
      padding: 3px 8px;
      border-radius: 4px;
      font-size: 0.625rem;
      font-weight: 600;
      white-space: nowrap;
      flex-shrink: 0;
    }

    .requirement-badge.required {
      background: rgba(221, 105, 58, 0.12);
      color: #DD693A;
    }

    .requirement-badge.suggested {
      background: rgba(70, 158, 146, 0.12);
      color: var(--cr-teal);
    }

    .brand-price {
      font-size: 0.8125rem;
      color: var(--slate-600);
      margin-top: 0;
    }

   .trust-sentence {
      font-size: 0.8125rem;
      color: var(--slate-600);
      margin-top: 8px;
      line-height: 1.4;
    }

  .size-note {
      font-size: 12px;
      color: var(--slate-500);
      font-style: italic;
      margin-top: 2px;
      line-height: 1.3;
    }

    .size-note.hidden {
      display: none;
    }

  /* Formula-mismatch card notice (laundry + cleaning). Renders between product
     details and the Add button when the product engine couldn't match the
     student's natural/practical preference at their tier. Louder than a trust
     sentence — it's a values signal, not a stylistic note. */
  .formula-mismatch-notice {
      background: var(--slate-50);
      border-left: 3px solid var(--cr-orange);
      border-radius: 4px;
      padding: 10px 12px;
      margin: 10px 0;
    }
  .formula-mismatch-lead {
      font-size: 12.5px;
      font-weight: 500;
      color: var(--slate-900);
      line-height: 1.4;
      margin-bottom: 2px;
    }
  .formula-mismatch-body {
      font-size: 12.5px;
      color: var(--slate-700);
      line-height: 1.45;
    }
  /* Empty slot collapses cleanly when the block isn't rendered */
  .formula-mismatch-slot:empty {
      display: none;
    }

  .btn-add-to-list {
      width: auto;
      padding: 8px 16px;
      margin-left: auto;
      border-radius: 8px;
      border: none;
      background: var(--cr-teal);
      color: var(--white);
      font-family: inherit;
      font-size: 0.875rem;
      font-weight: 600;
      cursor: pointer;
      transition: background 0.2s ease;
      flex-shrink: 0;
    }

    .btn-add-to-list:hover { background: var(--cr-teal-dark); }
    .btn-add-to-list:active { transform: scale(0.98); }

    .btn-add-to-list.added {
      background: var(--slate-200);
      color: var(--slate-600);
    }

    /* Small Product Card */
    .products-divider {
      display: flex;
      align-items: center;
      gap: 16px;
      margin: 24px 0 16px;
    }

    .products-divider::before,
    .products-divider::after {
      content: '';
      flex: 1;
      height: 1px;
      background: var(--slate-300);
    }

   .products-divider span {
      font-size: 0.8125rem;
      font-weight: 500;
      color: var(--slate-500);
    }

    .card-bottom-row { display: flex; justify-content: space-between; align-items: center; margin-top: 8px; min-width: 0; gap: 8px; }
    /* Color row: left-justified, allowed to shrink, color name truncates with
       ellipsis so the Add/Replace button on the right stays fully visible on
       narrow viewports (375px). The button has flex-shrink:0 so it never
       gives up width. */
    .color-change-row { display: flex; align-items: center; gap: 6px; cursor: pointer; -webkit-tap-highlight-color: transparent; min-width: 0; flex: 0 1 auto; overflow: hidden; }
    .color-change-swatch { width: 14px; height: 14px; border-radius: 50%; border: 1px solid rgba(0,0,0,0.08); flex-shrink: 0; }
    .color-change-name { font-family: var(--font-sans, 'DM Sans', sans-serif); font-size: 0.8125rem; font-weight: 400; color: var(--slate-500); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .color-change-sep { color: var(--slate-300); font-size: 0.8125rem; flex-shrink: 0; }
    .color-change-label { font-family: var(--font-sans, 'DM Sans', sans-serif); font-size: 0.8125rem; font-weight: 500; color: var(--cr-teal); flex-shrink: 0; }
    .shopping-card-container {
      background: var(--white);
      border: 1px solid var(--slate-200);
      border-radius: 20px;
      padding: 16px;
      box-shadow: var(--shadow-sm);
      margin-bottom: 16px;
    }

    .shopping-card-container .product-card-large {
      border: 1.5px solid #e2e8f0;
      border-radius: 12px;
      background: #ffffff;
      padding: 14px;
      margin-bottom: 10px;
    }

    .shopping-card-container .product-card-large:last-child {
      margin-bottom: 0;
    }

    .shopping-card-container .product-card-small {
      border: 1px solid var(--slate-100);
      margin-bottom: 8px;
    }

    .shopping-card-container .product-card-small:last-child {
      margin-bottom: 0;
    }

    .product-card-small {
      background: var(--white);
      border: 1px solid var(--slate-200);
      border-radius: 12px;
      padding: 14px;
      margin-bottom: 10px;
      display: grid;
      grid-template-columns: 72px 1fr auto;
      gap: 14px;
      align-items: center;
      cursor: pointer;
      transition: all 0.2s ease;
    }

    .product-card-small:hover {
      border-color: var(--slate-300);
      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
    }

    .small-image-wrap {
      width: 72px;
      height: 72px;
      border-radius: 8px;
      overflow: hidden;
      background: var(--slate-100);
      position: relative;
    }

    .small-image-wrap img {
      width: 100%;
      height: 100%;
      object-fit: contain;
      background: var(--slate-50);
    }

    .expand-hint {
      position: absolute;
      bottom: 4px;
      right: 4px;
      width: 20px;
      height: 20px;
      background: rgba(0, 0, 0, 0.5);
      border-radius: 4px;
      display: flex;
      align-items: center;
      justify-content: center;
    }

    .expand-hint svg {
      width: 12px;
      height: 12px;
      color: var(--white);
    }

   .small-card-info h3 {
      font-size: 0.75rem;
      font-weight: 400;
      color: var(--slate-500);
      margin-bottom: 2px;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }

    .small-card-info .brand-price {
      margin-top: 0;
      font-size: 0.8125rem;
    }

    .btn-add-compact {
      padding: 8px 16px;
      border-radius: 8px;
      border: none;
      background: var(--cr-teal);
      color: var(--white);
      font-family: inherit;
      font-size: 0.8125rem;
      font-weight: 600;
      cursor: pointer;
      transition: all 0.2s ease;
      white-space: nowrap;
    }

    .btn-add-compact:hover { background: var(--cr-teal-dark); }
    .btn-add-compact.added { background: var(--slate-200); color: var(--slate-600); }

    /* Lightbox */
    .lightbox-overlay {
      position: fixed;
      inset: 0;
      background: rgba(255, 255, 255, 0.92);
      backdrop-filter: blur(8px);
      -webkit-backdrop-filter: blur(8px);
      z-index: 1000;
      display: flex;
      flex-direction: column;
      opacity: 0;
      visibility: hidden;
      transition: all 0.3s ease;
    }

    .lightbox-overlay.visible {
      opacity: 1;
      visibility: visible;
    }

    .lightbox-close {
      position: absolute;
      top: 12px;
      right: 12px;
      width: 40px;
      height: 40px;
      background: var(--white);
      border: 0.5px solid var(--slate-200);
      border-radius: 50%;
      cursor: pointer;
      display: flex;
      align-items: center;
      justify-content: center;
      z-index: 10;
      box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
    }

    .lightbox-close:hover { background: var(--slate-100); }
    .lightbox-close svg { width: 24px; height: 24px; color: var(--slate-600); }

  .lightbox-content {
  position: relative;
  flex: 1;
  display: flex;
  flex-direction: column;
  max-width: 500px;
  width: 100%;
  margin: 0 auto;
  padding: 60px 24px 24px;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

    .lightbox-image-area {
      position: relative;
      width: 100%;
      aspect-ratio: 1 / 1;
      background: var(--slate-100);
      border-radius: 16px;
      overflow: hidden;
      border: 0.5px solid var(--slate-200);
    }

    .lightbox-track {
      display: flex;
      height: 100%;
      transition: transform 0.3s ease-out;
    }

    .lightbox-slide {
      position: relative;
      min-width: 100%;
      height: 100%;
      display: flex;
      align-items: center;
      justify-content: center;
    }

    .lightbox-slide img {
      max-width: 100%;
      max-height: 100%;
      object-fit: contain;
    }

    .lightbox-dots {
      display: flex;
      justify-content: center;
      gap: 8px;
      padding: 16px 0;
    }

    .lightbox-dot {
      width: 8px;
      height: 8px;
      border-radius: 4px;
      background: var(--slate-300);
      cursor: pointer;
      border: none;
      padding: 0;
      transition: all 0.2s ease;
    }

    .lightbox-dot.active {
      background: var(--slate-700);
    }

    .lightbox-info {
      background: var(--white);
      border-radius: 16px;
      padding: 20px;
      margin-top: 16px;
      border: 0.5px solid var(--slate-200);
      box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
    }

      .lightbox-info h3 {
      font-size: 0.9375rem;
      font-weight: 400;
      color: var(--slate-600);
      margin-bottom: 4px;
    }

    .lightbox-info .trust-sentence {
      margin-top: 12px;
      margin-bottom: 0px;
    }

    .lightbox-info .btn-add-to-list { margin-top: 16; }

     .lightbox-arrow {
      position: absolute;
      top: 50%;
      transform: translateY(-50%);
      width: 36px;
      height: 36px;
      border-radius: 50%;
      background: rgba(255, 255, 255, 0.9);
      border: 1.5px solid #469E92;
      box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
      cursor: pointer;
      display: flex;
      align-items: center;
      justify-content: center;
      z-index: 5;
      transition: all 0.2s ease;
    }

    .lightbox-arrow:hover { background: var(--slate-100); }
     .lightbox-arrow svg {
      width: 18px;
      height: 18px;
      color: var(--slate-700);
    }

    .lightbox-arrow-left { left: 12px; }
    .lightbox-arrow-right { right: 12px; }

    .lightbox-arrow.hidden { opacity: 0; pointer-events: none; }

    /* Floating Cart — sits above the bottom nav.
       The bottom offset must include env(safe-area-inset-bottom) because the
       bottom nav itself grew by that amount on iOS devices with home indicators
       (see .bottom-nav rule in layout.css). Without this addition, the floating
       cart sat at 68px from the screen edge while the nav extended to ~89px,
       overlapping the top of the nav icons on iPad landscape. env() resolves
       to 0 on devices without a safe area, so this is a no-op on desktop. */
    .floating-cart {
      position: fixed;
      bottom: calc(68px + env(safe-area-inset-bottom));
      left: 0;
      right: 0;
      background: var(--white);
      border-top: 1px solid var(--slate-200);
      padding: 16px 24px;
      box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.08);
      z-index: 100;
      display: none;
      max-width: 600px;
      margin: 0 auto;
    }

    .floating-cart.visible { display: block; }

    .floating-cart-inner {
      max-width: 600px;
      margin: 0 auto;
      display: flex;
      justify-content: space-between;
      align-items: center;
    }

    .cart-summary {
      display: flex;
      align-items: center;
      gap: 12px;
    }

    .cart-icon-wrap {
      width: 40px;
      height: 40px;
      background: var(--cr-teal);
      border-radius: 10px;
      display: flex;
      align-items: center;
      justify-content: center;
      position: relative;
    }

    .cart-icon-wrap svg { width: 20px; height: 20px; color: var(--white); }

    .cart-badge {
      position: absolute;
      top: -4px;
      right: -4px;
      background: var(--cr-orange);
      color: var(--white);
      font-size: 0.6875rem;
      font-weight: 700;
      width: 18px;
      height: 18px;
      border-radius: 9px;
      display: flex;
      align-items: center;
      justify-content: center;
    }

    .cart-text {
      font-size: 0.9375rem;
      color: var(--slate-700);
    }

    .cart-text strong {
      font-weight: 600;
      color: var(--slate-900);
    }

    .save-list-link {
      font-size: 0.875rem;
      font-weight: 600;
      color: white;
      text-decoration: none;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      padding: 14px 20px;
      border: none;
      border-radius: 12px;
      background: var(--slate-700);
      transition: background 0.15s ease;
      /* Width formula mirrors #continueToShopBtn / #chooseAnotherCategory:
         (container_inner - 12px_gap) / 2. Cart bar shares the same 600px
         max-width as the checklist footer, so the pill caps at ~278px on
         desktop (visually matches a single CTA) and shrinks on narrow
         viewports without needing a media query. */
      width: calc(50% - 6px);
      box-sizing: border-box;
    }
    .save-list-link:hover { background: var(--slate-800); }
    .save-list-link svg { color: white; }

    /* Shopping screen needs bottom padding to clear BOTH the bottom nav (~68px
       + safe-area inset) AND the floating cart bar (~80px tall, sits above nav).
       Previous 100px reserved space only for the nav, leaving the final
       "See my list" button hidden behind the floating cart on completed
       categories. 180px clears both with breathing room. env() adds iOS
       home-indicator clearance on top; resolves to 0 on desktop. */
    .shopping-screen .container { padding-bottom: calc(180px + env(safe-area-inset-bottom)); }

.shopping-change-prefs {
  display: block;
  text-align: center;
  color: #DD693A;
  font-size: 0.8125rem;
  font-weight: 500;
  margin-top: 12px;
  text-decoration: none;
  transition: color 0.2s ease;
}

.shopping-change-prefs:hover {
  text-decoration: underline;
}

.shopping-pref-link {
  display: block;
  text-align: center;
  color: #DD693A;
  font-size: 0.8125rem;
  font-weight: 500;
  padding: 8px 0 16px;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

/* Persistent guidance banner — passive informational note matching
   My List quantity note treatment (DEC-671) */
.guidance-banner {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  background: var(--slate-100);
  border: 1px solid var(--slate-300);
  border-radius: 8px;
  padding: 10px 12px;
  margin-bottom: 16px;
  color: var(--slate-500);
}

.guidance-banner span {
  font-family: var(--font-sans);
  font-size: 0.8125rem;
  font-weight: 400;
  color: var(--slate-600);
  line-height: 1.45;
}

.guidance-banner svg {
  flex-shrink: 0;
  margin-top: 1px;
}

.guidance-banner.animate-entrance {
  animation: guidanceFadeIn 400ms ease-out 300ms both;
}

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

/* Two-button shopping layout — "See my list" + "Continue to [Category]" */
.shopping-bottom-btns {
  display: flex;
  gap: 12px;
  margin-top: 24px;
}

.shopping-btn-list {
  flex: 1;
  padding: 14px 0;
  border-radius: 12px;
  background: var(--cr-teal);
  border: none;
  font-family: var(--font-sans);
  font-size: 0.9375rem;
  font-weight: 600;
  color: white;
  cursor: pointer;
  transition: all 0.15s ease;
  -webkit-tap-highlight-color: transparent;
}
.shopping-btn-list:hover { background: var(--cr-teal-dark); }
.shopping-btn-list:active { transform: scale(0.98); }

.shopping-btn-next {
  flex: 1;
  padding: 14px 0;
  border-radius: 12px;
  background: var(--slate-800);
  border: none;
  font-family: var(--font-sans);
  font-size: 0.9375rem;
  font-weight: 600;
  color: white;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  transition: all 0.15s ease;
  -webkit-tap-highlight-color: transparent;
}
.shopping-btn-next:active { transform: scale(0.98); }
.shopping-btn-next svg { width: 16px; height: 16px; }

/* Final category — single full-width teal CTA */
.shopping-btn-final {
  width: 100%;
  margin-top: 24px;
  padding: 14px;
  border-radius: 12px;
  background: var(--cr-teal);
  border: none;
  font-family: var(--font-sans);
  font-size: 0.9375rem;
  font-weight: 600;
  color: white;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  transition: background 0.15s ease;
  -webkit-tap-highlight-color: transparent;
}
.shopping-btn-final:hover { background: var(--cr-teal-dark); }
.shopping-btn-final:active { transform: scale(0.98); }

/* ─── Mobile: tighten badge counter ─── */
@media (max-width: 600px) {
  .product-options-badge {
    font-size: 10px;
    padding: 3px 6px;
  }
}

/* ──────────────────────────────────────────────────────────────
   MOBILE: full-width color row
   On narrow viewports the inline color row inside .card-bottom-row
   (large) and .small-card-info (small) gets squeezed by the Add/Replace
   button and the color name truncates. Hide the inline copy and show
   the card-level .color-change-row-mobile sibling as a full-width row
   below the card body, left-aligned with the image edge.
   ────────────────────────────────────────────────────────────── */
@media (max-width: 768px) {
  /* ── Large card ── */
  .product-card-large {
    grid-template-columns: 140px 1fr;
    grid-template-areas:
      "image content"
      "color color";
  }
  .product-card-large > .image-carousel { grid-area: image; }
  .product-card-large > .card-content   { grid-area: content; }
  .product-card-large > .color-change-row-mobile {
    grid-area: color;
    display: flex;
    align-items: center;
    /* min-height matches the absolute Add button below so the flex-centered
       swatch + name + Change link sit at the same vertical center as the
       button. The right padding reserves room for the absolutely positioned
       button (≈70px wide at right: 14px) so the color name truncates with
       ellipsis instead of running underneath the button. */
    min-height: 36px;
    padding: 0 100px 0 6px;
    margin-bottom: 12px;
  }
  .product-card-large .card-bottom-row > .color-change-row { display: none; }

  /* When a mobile color row is present on the large card, the inline Add
     button (which lives inside .card-bottom-row inside .card-content) is
     pulled out of flow and anchored to the bottom-right of the card's
     padding box. This places it on the same horizontal line as the mobile
     color row in grid row 2, vertically centered with the color text
     (matching min-heights). Cards without a color row keep the inline
     button in its original position inside .card-bottom-row. */
  .product-card-large:has(> .color-change-row-mobile) {
    position: relative;
  }
  .product-card-large:has(> .color-change-row-mobile) .card-bottom-row {
    /* The bottom row's only flow children are now hidden (inline color row)
       or absolute (Add button), so zero out its space contribution to keep
       .card-content from leaving an 8px gap below the trust sentence. */
    margin-top: 0;
    min-height: 0;
  }
  .product-card-large:has(> .color-change-row-mobile) .card-bottom-row > .btn-add-to-list {
    position: absolute;
    right: 14px;
    /* Anchored to the card's padding box, which sits 14px above the grid's
       content box. The mobile color row inside grid row 2 therefore sits
       higher than `bottom: 12px` would suggest, and the button (≈44px tall,
       not the 36px the color row min-heights to) rides ~10px low against the
       color text center. Bumping bottom by 10px → 22px raises the button
       center the same 10px so it matches the "White · Change" text center.
       Reference: small card uses pure grid alignment which is exact. */
    bottom: 22px;
  }

  /* ── Small card ── */
  .product-card-small {
    grid-template-columns: 72px 1fr auto;
    grid-template-areas:
      "image info button"
      "color color color";
  }
  .product-card-small > .small-image-wrap { grid-area: image; }
  .product-card-small > .small-card-info  { grid-area: info; }
  .product-card-small > .btn-add-compact  { grid-area: button; }
  .product-card-small > .color-change-row-mobile {
    grid-area: color;
    display: flex;
    /* The grid's gap: 14px already provides separation from row 1, and the
       card's padding: 14px handles spacing to the bottom edge. No extra
       padding needed on the row itself. */
  }
  .product-card-small .small-card-info > .color-change-row { display: none; }

  /* When a mobile color row is present on the small card, restructure the
     grid so the Add button moves down into row 2 alongside the color row
     (instead of sitting up in row 1 col 3). Both share row 2 and inherit
     align-items: center from the parent, so they're vertically centered on
     the same horizontal line. Cards without a color row don't match :has()
     and keep the default "image info button" layout above. */
  .product-card-small:has(> .color-change-row-mobile) {
    grid-template-areas:
      "image info ."
      "color color button";
  }
}

/* ══════════════════════════════════════════════════════════════
   COMPARISON PANEL — bottom-sheet for PANEL_ELIGIBLE types
   ══════════════════════════════════════════════════════════════ */

/* ── Overlay ── */
.cp-overlay {
  position: fixed; inset: 0; z-index: 1100;
  background: rgba(0, 0, 0, 0.4);
  opacity: 0; pointer-events: none;
  transition: opacity 0.25s ease;
}
.cp-overlay.visible { opacity: 1; pointer-events: auto; }

/* ── Panel shell (mobile: floating card bottom-sheet) ── */
.cp-panel {
  position: fixed; bottom: 8px; left: 10px; right: 10px; z-index: 1101;
  background: var(--white);
  border-radius: 16px;
  transform: translateY(calc(100% + 8px));
  transition: transform 0.3s var(--ease-out);
  display: flex; flex-direction: column;
  max-height: 72vh;
  box-shadow: 0 4px 24px rgba(0, 0, 0, 0.15);
  pointer-events: none;
}
.cp-panel.open { transform: translateY(0); pointer-events: auto; }

/* ── Accent bar ── */
.cp-accent { height: 4px; background: var(--school-primary); border-radius: 16px 16px 0 0; flex-shrink: 0; overflow: hidden; }

/* ── Drag handle ── */
.cp-drag { display: flex; justify-content: center; padding: 10px 0 4px; cursor: grab; flex-shrink: 0; }
.cp-drag-bar { width: 36px; height: 4px; background: var(--slate-300); border-radius: 2px; }

/* ── Header ── */
.cp-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 4px 16px 12px; flex-shrink: 0;
}
.cp-title { font-size: 1.0625rem; font-weight: 600; color: var(--slate-900); }
.cp-close {
  width: 32px; height: 32px;
  display: flex; align-items: center; justify-content: center;
  border: none; background: var(--slate-100); border-radius: 50%;
  cursor: pointer; color: var(--slate-500); font-size: 16px; flex-shrink: 0;
  transition: background 0.15s;
}
.cp-close:active { background: var(--slate-200); }

/* ── Scrollable body ── */
.cp-body {
  overflow-y: auto; flex: 1; min-height: 0;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  scroll-behavior: smooth;
}

/* ══════════════════════════════════════
   VERTICAL LAYOUT (mobile default)
   ══════════════════════════════════════ */
.cp-row {
  display: flex; gap: 12px; padding: 14px 16px;
  border-bottom: 1px solid var(--slate-100);
  cursor: pointer; transition: background 0.15s ease, border-color 0.15s ease;
  position: relative; border-left: 3px solid transparent;
}
.cp-row:last-child { border-bottom: none; }
.cp-row:active { background: var(--slate-50); }

/* Selected state */
.cp-row.cp-selected {
  background: rgba(70, 158, 146, 0.04);
  border-left-color: var(--cr-teal);
}

/* ── Product image ── */
.cp-img-wrap { flex-shrink: 0; width: 80px; height: 80px; }
.cp-img {
  width: 100%; height: 100%; border-radius: 10px;
  object-fit: cover; background: var(--slate-100); display: block;
}

/* ── Product info ── */
.cp-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }

/* Badge row */
.cp-badge-row { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; min-height: 18px; }
.cp-our-pick {
  display: inline-block; background: rgba(221, 105, 58, 0.75); color: var(--white);
  font-size: 10px; font-weight: 600; padding: 2px 6px; border-radius: 4px; line-height: 1.3;
}
.cp-in-list {
  display: none; font-size: 10px; color: var(--slate-500);
  font-weight: 500; line-height: 1.3;
}
.cp-row.cp-in-cart .cp-in-list,
.cp-col.cp-in-cart .cp-in-list { display: inline; }

/* Product text */
.cp-name { font-size: 0.8125rem; font-weight: 600; color: var(--slate-900); line-height: 1.35; }
.cp-meta { font-size: 0.75rem; font-weight: 400; color: var(--slate-500); line-height: 1.4; }
.comparison-rating { font-size: 0.8125rem; color: var(--slate-600); margin-top: 4px; margin-bottom: 8px; line-height: 1.3; }
.comparison-rating .star { color: #F59E0B; }
.cp-summary {
  font-size: 0.75rem; font-weight: 400; color: var(--slate-500);
  font-style: italic; line-height: 1.4; margin-top: 2px;
}

/* Learn more link */
.cp-learn-more {
  font-family: var(--font-sans); font-size: 0.75rem; font-weight: 500;
  color: var(--cr-teal); background: none; border: none;
  padding: 0; cursor: pointer; text-align: left; margin-top: 3px; margin-bottom: 8px;
}
.cp-learn-more:hover { text-decoration: underline; }

/* Detail expansion */
.cp-detail {
  display: none; font-size: 0.75rem; font-weight: 400; color: var(--slate-700);
  line-height: 1.5; margin-top: 4px; padding-top: 4px;
  border-top: 1px solid var(--slate-100);
}
.cp-detail.cp-detail-open { display: block; }
.cp-detail p { margin-bottom: 6px; }
.cp-detail ul { margin: 0; padding-left: 16px; }
.cp-detail ul li { margin-bottom: 2px; }

/* ── Action button (always visible so user can act on any product) ── */
.cp-action-btn {
  display: block;
  font-family: var(--font-sans); font-size: 0.8125rem; font-weight: 600;
  color: var(--cr-teal); background: var(--white);
  border: 1.5px solid var(--cr-teal);
  padding: 10px 20px; border-radius: 10px;
  cursor: pointer; margin-top: auto; padding-top: 8px; width: 100%;
  transition: background 0.15s ease, color 0.15s ease;
}
.cp-action-btn:active { background: var(--cr-teal); color: var(--white); }
.cp-selected .cp-action-btn {
  background: var(--cr-teal); color: var(--white);
}
.cp-action-added {
  background: var(--cr-teal); color: var(--white); border-color: var(--cr-teal);
}

/* ── Static image for PANEL_ELIGIBLE large cards ── */
.cp-static-wrap { position: relative; cursor: pointer; }
.cp-static-img {
  width: 100%; height: 100%; object-fit: cover;
  border-radius: 12px 12px 0 0;
}

/* ══════════════════════════════════════
   HORIZONTAL LAYOUT (desktop, >768px)
   ══════════════════════════════════════ */
@media (min-width: 769px) {
  /* Desktop: centered modal instead of bottom sheet */
  .cp-panel {
    inset: auto;
    top: 50%; left: 50%;
    max-width: 760px; width: calc(100% - 48px);
    border-radius: 16px;
    transform: translate(-50%, -50%) scale(0.95);
    opacity: 0;
    transition: transform 0.25s var(--ease-out), opacity 0.25s ease;
    max-height: 75vh;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.2);
  }
  .cp-panel.open {
    transform: translate(-50%, -50%) scale(1);
    opacity: 1;
  }

  .cp-body-inner {
    display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 0;
  }

  /* Switch from rows to columns */
  .cp-row {
    flex-direction: column; gap: 8px;
    padding: 14px 12px;
    border-bottom: none; border-right: 1px solid var(--slate-100);
    border-left: none; border-top: 3px solid transparent;
  }
  .cp-row:last-child { border-right: none; }

  /* Selected uses top border instead of left */
  .cp-row.cp-selected {
    border-left-color: transparent;
    border-top-color: var(--cr-teal);
  }

  /* Image fills column width, capped height for tall product packaging */
  .cp-img-wrap { width: 100%; height: auto; aspect-ratio: 1 / 1; max-height: 200px; }
  .cp-img { object-fit: contain; }

  /* Tighter text for columns */
  .cp-name {
    font-size: 0.75rem; line-height: 1.3;
    display: -webkit-box; -webkit-line-clamp: 2;
    -webkit-box-orient: vertical; overflow: hidden;
  }
  .cp-meta { font-size: 0.6875rem; }
  .comparison-rating { font-size: 0.75rem; margin-top: 2px; margin-bottom: 6px; }
  .cp-summary {
    font-size: 0.6875rem; line-height: 1.35;
    display: -webkit-box; -webkit-line-clamp: 3;
    -webkit-box-orient: vertical; overflow: hidden;
  }
  .cp-summary.cp-summary-expanded { -webkit-line-clamp: unset; display: block; }
  .cp-learn-more { font-size: 0.6875rem; }
  .cp-detail { font-size: 0.6875rem; line-height: 1.4; }
  .cp-detail ul { padding-left: 12px; }
  .cp-our-pick { font-size: 9px; padding: 1px 5px; }
  .cp-in-list { font-size: 9px; }
  .cp-badge-row { min-height: 16px; }
  .cp-action-btn { font-size: 0.75rem; padding: 8px 14px; }
}


/* ==================== SHOPPING SKELETON LOADING ==================== */
/* Skeletons reuse the real .product-card-large / .product-card-small /
   .image-carousel / .small-image-wrap / .card-content / .card-bottom-row /
   .btn-add-to-list / .btn-add-compact classes for geometry inheritance,
   so every dimension, border, padding, grid layout, and responsive
   breakpoint comes from the real card rules automatically. Only the
   visual treatment inside those shells (text lines, button fill, image
   shimmer) is overridden here. */

/* Container fades in and out. pointer-events:none blocks any stray taps on
   skeleton cards during the show window. */
.shopping-skeleton-container {
  opacity: 0;
  transition: opacity 180ms ease-out;
  pointer-events: none;
}
.shopping-skeleton-container.visible { opacity: 1; }
.shopping-skeleton-container.fading-out { opacity: 0; }

/* Skeleton cards: neutralize real card's interactive affordances so they
   don't read as tappable. Pointer-events on the container already blocks
   input; these rules neutralize the hover visuals. */
.skeleton-card { cursor: default; }
.skeleton-card:hover {
  border-color: inherit !important;
  box-shadow: none !important;
}

/* Shimmer on the image slots. The real .image-carousel (128x163) and
   .small-image-wrap (72x72) define all the geometry — this rule only
   paints the animated gradient over the existing grey background. */
.skeleton-card .skeleton-image {
  background: linear-gradient(
    90deg,
    var(--slate-100) 25%,
    var(--slate-50) 50%,
    var(--slate-100) 75%
  );
  background-size: 200% 100%;
  animation: skeleton-pulse 1.5s ease-in-out infinite;
}

/* Text line placeholders. Widths and heights mirror the rhythm of real
   content observed on staging: short bold label, long product name,
   medium brand·price, long trust sentence wrapping to partial second
   line. Margins mirror real typography spacing (product-type-label
   margin-bottom 2px, trust-sentence margin-top 8px). */
.skeleton-line {
  background: var(--slate-100);
  border-radius: 4px;
}
.skeleton-line-label   { height: 15px; width: 32%; margin-bottom: 4px; }
.skeleton-line-name    { height: 13px; width: 78%; margin-bottom: 6px; }
.skeleton-line-brand   { height: 13px; width: 42%; margin-bottom: 8px; }
.skeleton-line-trust-a { height: 13px; width: 85%; margin-bottom: 4px; }
.skeleton-line-trust-b { height: 13px; width: 45%; margin-bottom: 0; }

/* Skeleton buttons use the real .btn-add-to-list / .btn-add-compact
   classes for dimensions (padding, border-radius, font-size, font-weight
   drive width/height). This rule only neutralizes color + interactivity,
   so if the real button sizing changes, the skeleton adapts. The &nbsp;
   inside the button provides content so line-height resolves correctly. */
.skeleton-btn {
  background: var(--slate-100) !important;
  color: transparent !important;
  cursor: default !important;
}
.skeleton-btn:hover { background: var(--slate-100) !important; }

@keyframes skeleton-pulse {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

@media (prefers-reduced-motion: reduce) {
  .skeleton-card .skeleton-image {
    animation: none;
    background: var(--slate-100);
  }
}
