/* ---------------------------------------------------------------------------
   phase2.css — Corporate Gift Phase 2 UI.

   Covers the pieces added in Phase 2: the two-path homepage block, the
   individual-product catalogue and product page, and the gift-message and
   packaging configurator. It reuses the existing palette variables from
   style.css so the brand stays in one place.
   ------------------------------------------------------------------------- */

/* ===== Two paths (homepage) ============================================== */
.cg-paths { padding: 64px 0; background: var(--ng-off-white); }
.cg-paths__inner { max-width: 1120px; margin: 0 auto; padding: 0 20px; }
.cg-paths h2 { margin: 0 0 8px; font-size: clamp(1.6rem, 3vw, 2.2rem); }
.cg-paths__lede { color: var(--ng-grey); max-width: 62ch; margin: 0 0 28px; }
/* min(300px, 100%) rather than a bare 300px: on a 320px phone the container is
   narrower than the track minimum, and a bare value would push the card past
   the screen edge. */
.cg-paths__grid { display: grid; gap: 20px; grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); }

.cg-path {
  display: block; position: relative; padding: 32px 28px 28px;
  border: 1px solid var(--ng-line); border-radius: 14px;
  background: var(--ng-white); color: inherit; text-decoration: none;
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
.cg-path:hover { transform: translateY(-3px); box-shadow: 0 14px 34px rgba(0,0,0,.10); border-color: var(--ng-gold); }
.cg-path__num {
  display: grid; place-items: center; width: 34px; height: 34px; border-radius: 50%;
  background: var(--ng-navy); color: var(--ng-gold); font-weight: 700; margin-bottom: 14px;
}
.cg-path h3 { margin: 0 0 8px; font-size: 1.25rem; }
.cg-path p { margin: 0 0 16px; color: var(--ng-grey); line-height: 1.6; }
.cg-path__cta { font-weight: 600; color: var(--ng-navy); }
.cg-path--alt { background: var(--ng-navy); color: var(--ng-silver); border-color: var(--ng-navy); }
.cg-path--alt h3 { color: var(--ng-white); }
.cg-path--alt p { color: #BFBFBF; }
.cg-path--alt .cg-path__num { background: var(--ng-gold); color: var(--ng-navy); }
.cg-path--alt .cg-path__cta { color: var(--ng-gold); }

/* ===== Catalogue ========================================================= */
.cg-catalogue h1 { margin-bottom: 6px; }
.cg-promise {
  display: inline-block; margin: 4px 0 20px; padding: 8px 14px; border-radius: 999px;
  background: rgba(201,162,75,.14); color: var(--ng-ink); font-weight: 600; font-size: .92rem;
}
.cg-count { color: var(--ng-grey); margin: 8px 0 16px; }
.cg-empty { padding: 28px; background: var(--ng-off-white); border: 1px solid var(--ng-line); border-radius: 12px; }

.cg-filters { margin: 18px 0 26px; padding: 18px; border: 1px solid var(--ng-line); border-radius: 12px; }
.cg-filters__row { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
.cg-filters__search { flex: 1 1 260px; padding: 11px 14px; border: 1px solid var(--ng-line); border-radius: 8px; font: inherit; }
.cg-filters select { padding: 11px 12px; border: 1px solid var(--ng-line); border-radius: 8px; font: inherit; }

.cg-filters__zones { display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr)); margin-top: 16px; }
.cg-zone { border: 1px solid var(--ng-line); border-radius: 10px; padding: 12px 14px; }
.cg-zone legend { font-weight: 700; font-size: .85rem; text-transform: uppercase; letter-spacing: .06em; padding: 0 6px; }
.cg-zone--exclude legend { color: var(--ng-danger); }
.cg-chip { display: inline-flex; align-items: center; gap: 6px; margin: 4px 6px 4px 0; padding: 6px 11px;
  border: 1px solid var(--ng-line); border-radius: 999px; cursor: pointer; font-size: .88rem; }
.cg-chip:has(input:checked) { background: var(--ng-navy); color: var(--ng-white); border-color: var(--ng-navy); }
.cg-zone--exclude .cg-chip:has(input:checked) { background: var(--ng-danger); border-color: var(--ng-danger); }
.cg-chip input { accent-color: var(--ng-gold); }

.cg-grid { margin-top: 8px; }
.card--component { display: flex; flex-direction: column; }
.cg-card__body { padding: 12px 14px 16px; display: flex; flex-direction: column; gap: 8px; }
.cg-card__price { font-weight: 700; font-size: 1.1rem; }
.cg-card__avail { font-size: .85rem; font-weight: 600; }
.cg-card__avail--ok { color: var(--ng-success); }
.cg-card__avail--virtual { color: var(--ng-gold); }
.cg-card__avail--none { color: var(--ng-danger); }
.cg-card__add { display: flex; gap: 8px; }
.cg-card__add input { width: 72px; padding: 8px 10px; border: 1px solid var(--ng-line); border-radius: 8px; font: inherit; }

/* The dispatch date lives in the session and silently filters the whole
   catalogue, so the page it filters has to admit it is doing so — and offer the
   way out in the same breath, or the shopper has no route back to ASAP. */
.dispatch-banner {
  display: flex; flex-wrap: wrap; gap: 8px 16px; align-items: center;
  justify-content: space-between; font-size: .9rem;
  background: var(--ng-off-white); border: 1px solid var(--ng-line);
}
.dispatch-widget__note { flex: 1 1 100%; display: block; font-size: .82rem; }

.cg-flaglist { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 5px; }
.cg-flag { font-size: .74rem; padding: 3px 8px; border-radius: 999px; background: var(--ng-off-white); border: 1px solid var(--ng-line); color: var(--ng-grey); }
.cg-flag--allergen { border-color: #E4B9B4; background: #FDF3F2; color: #8B2F25; }
.cg-flag--alcohol { border-color: #D9C39A; background: #FBF6EA; color: #7A5B1E; }
.cg-flag--diet { border-color: #B7DBC0; background: #F1FAF3; color: #23643A; }

.cg-crosssell { margin: 56px 0 12px; padding: 28px; border-radius: 14px; background: var(--ng-navy); color: var(--ng-silver); }
.cg-crosssell h2 { color: var(--ng-white); margin-top: 0; }

/* ===== Departments =======================================================
   The shop's front door. A tile is a whole link rather than a card with a link
   inside it, so the entire block is one target — on a phone the blurb is the
   biggest thing on the tile and tapping it has to go somewhere.

   Same track idiom as .cg-paths__grid above: min(260px, 100%) rather than a
   bare 260px, because on a 320px phone the container is narrower than the track
   minimum and a bare value pushes the tile past the screen edge — a horizontal
   scrollbar on the page a shopper lands on first.
   ======================================================================== */
.cg-depts {
  display: grid; gap: 18px; margin: 8px 0 4px;
  grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
}
.cg-dept {
  display: flex; flex-direction: column; padding: 22px 22px 18px;
  border: 1px solid var(--ng-line); border-radius: 14px;
  background: var(--ng-white); color: inherit; text-decoration: none;
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
.cg-dept:hover { transform: translateY(-3px); box-shadow: 0 14px 34px rgba(0,0,0,.10); border-color: var(--ng-gold); }
/* The heading is an h2 for the document outline, but it is a label on a tile,
   not the headline of a section, so it is sized like the card titles rather
   than like the global h2. */
.cg-dept__name { margin: 0 0 8px; font-size: 1.18rem; line-height: 1.25; color: var(--ng-navy); }
.cg-dept__blurb { margin: 0 0 16px; color: var(--ng-grey); line-height: 1.6; font-size: .93rem; }
/* Pushed to the bottom so the count sits on the same line across a row however
   long the blurbs are — a ragged row of numbers reads as unfinished. */
.cg-dept__count {
  margin-top: auto; align-self: flex-start; padding: 5px 12px; border-radius: 999px;
  background: rgba(201,162,75,.14); color: var(--ng-ink); font-weight: 600; font-size: .85rem;
}
/* The departments cover the mapped categories only, so the flat grid stays one
   click away and has to look like a deliberate offer rather than a footnote. */
.cg-browse-all { margin: 22px 0 4px; font-weight: 600; }
.cg-browse-all a { color: var(--ng-navy); }

/* Refine: the categories inside a department that have stock. Links, not a
   <select>, because each one is a real address worth sharing and crawling —
   and because a chip row shows the counts, which a dropdown cannot. */
.cg-refine { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 20px; }
.cg-refine__chip {
  display: inline-flex; align-items: center; gap: 6px; min-height: 36px;
  padding: 6px 12px; border: 1px solid var(--ng-line); border-radius: 999px;
  font-size: .88rem; font-weight: 600; color: var(--ng-ink); text-decoration: none;
  background: var(--ng-white);
}
.cg-refine__chip:hover { border-color: var(--ng-gold); }
.cg-refine__chip.is-current { background: var(--ng-navy); color: var(--ng-white); border-color: var(--ng-navy); }
/* The count is supporting detail, so it recedes — at full weight the number
   competed with the category name it belongs to. */
.cg-refine__n { color: var(--ng-grey); font-weight: 500; font-size: .8rem; }
.cg-refine__chip.is-current .cg-refine__n { color: var(--ng-gold); }
@media (max-width: 700px) {
  .cg-dept { padding: 18px; }
  .cg-refine { gap: 6px; }
  /* 40px, not 36: on a phone these are the primary navigation of the page and
     have to clear the minimum tap target. */
  .cg-refine__chip { min-height: 40px; }
}

/* ===== Single component page ============================================ */
.cg-crumbs { display: flex; gap: 8px; margin-bottom: 16px; font-size: .9rem; color: var(--ng-grey); }
.cg-crumbs a { color: var(--ng-grey); }
.cg-product__layout { display: grid; gap: 36px; grid-template-columns: minmax(min(280px, 100%), 1fr) minmax(min(300px, 100%), 1fr); align-items: start; }
@media (max-width: 820px) { .cg-product__layout { grid-template-columns: 1fr; } }
/* The global h1 is sized for page titles (up to 3rem). A component name is a
   label on a product, not the headline of an article, and at that size it
   pushed the price and the Add row below the fold. Scoped here so page titles
   elsewhere keep their weight. */
.cg-product__detail h1 { font-size: clamp(1.45rem, 2.4vw, 1.75rem); line-height: 1.2; margin: 0 0 .35rem; }
.cg-product__brand { color: var(--ng-grey); text-transform: uppercase; letter-spacing: .08em; font-size: .82rem; }
.cg-product__price { font-size: 1.7rem; font-weight: 700; margin: 12px 0 18px; }
.cg-product__desc { line-height: 1.7; margin-bottom: 20px; }
.cg-product__flags h2 { font-size: 1rem; margin-bottom: 8px; }
.cg-product__allergen-note { font-size: .84rem; color: var(--ng-grey); margin-top: 10px; }
.cg-product__avail { margin: 20px 0; padding: 14px 16px; border-radius: 10px; background: var(--ng-off-white); border-left: 4px solid var(--ng-line); }
.cg-product__avail--ok { border-left-color: var(--ng-success); }
.cg-product__avail--virtual { border-left-color: var(--ng-gold); }
.cg-product__avail--none { border-left-color: var(--ng-danger); }
.cg-product__avail p { margin: 6px 0 0; font-size: .9rem; color: var(--ng-grey); }
.cg-product__add { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 16px; }
.cg-product__add input { width: 92px; padding: 11px 12px; border: 1px solid var(--ng-line); border-radius: 8px; font: inherit; }
.cg-product__next { font-size: .88rem; color: var(--ng-grey); }

/* ===== Configurator ===================================================== */
.cg-config__line { margin: 26px 0; border: 1px solid var(--ng-line); border-radius: 14px; overflow: hidden; }
.cg-config__head { display: flex; justify-content: space-between; align-items: center; gap: 12px;
  padding: 16px 22px; background: var(--ng-navy); color: var(--ng-white); }
.cg-config__head h2 { margin: 0; font-size: 1.1rem; color: var(--ng-white); }
.cg-config__qty { color: var(--ng-gold); font-weight: 700; }
.cg-config__block { border: 0; border-top: 1px solid var(--ng-line); margin: 0; padding: 20px 22px; }
.cg-config__block legend { font-weight: 700; font-size: .85rem; text-transform: uppercase; letter-spacing: .06em; }
.cg-hint { color: var(--ng-grey); font-size: .9rem; margin: 4px 0 14px; line-height: 1.6; }

.cg-cards { display: grid; gap: 10px; grid-template-columns: repeat(auto-fill, minmax(min(190px, 100%), 1fr)); margin-bottom: 16px; }
.cg-card-opt { display: block; padding: 12px 14px; border: 1px solid var(--ng-line); border-radius: 10px; cursor: pointer; }
.cg-card-opt.is-selected, .cg-card-opt:has(input:checked) { border-color: var(--ng-gold); box-shadow: inset 0 0 0 1px var(--ng-gold); }
.cg-card-opt input { margin-right: 8px; accent-color: var(--ng-gold); }
.cg-card-opt__body strong { display: block; }
.cg-card-opt__body small { color: var(--ng-grey); }

.cg-field { display: block; margin: 12px 0; }
.cg-field > span { display: block; font-weight: 600; margin-bottom: 6px; font-size: .9rem; }
.cg-field textarea, .cg-field select, .cg-field input[type="file"] {
  width: 100%; padding: 11px 12px; border: 1px solid var(--ng-line); border-radius: 8px; font: inherit;
}

.cg-logo-preview { display: grid; gap: 18px; grid-template-columns: 200px 1fr; align-items: start;
  padding: 16px; background: var(--ng-off-white); border: 1px solid var(--ng-line); border-radius: 10px; }
@media (max-width: 640px) { .cg-logo-preview { grid-template-columns: 1fr; } }
.cg-logo-preview img { width: 100%; height: auto; background:
  repeating-conic-gradient(#EDEDED 0 25%, #FFF 0 50%) 50% / 18px 18px; border: 1px solid var(--ng-line); border-radius: 6px; }
.cg-warnings { margin: 10px 0; padding-left: 18px; }
.cg-warnings li { color: #8B4A00; margin-bottom: 8px; line-height: 1.55; font-size: .9rem; }
.cg-ok { color: var(--ng-success); font-weight: 600; }
.cg-confirm { display: flex; gap: 8px; align-items: flex-start; margin-top: 10px; font-size: .9rem; }
.cg-confirm input { margin-top: 3px; accent-color: var(--ng-gold); }

.cg-pack { display: grid; gap: 10px; grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); }
.cg-pack-opt { display: flex; gap: 10px; padding: 14px; border: 1px solid var(--ng-line); border-radius: 10px; cursor: pointer; }
.cg-pack-opt.is-selected, .cg-pack-opt:has(input:checked) { border-color: var(--ng-gold); box-shadow: inset 0 0 0 1px var(--ng-gold); }
.cg-pack-opt strong { display: block; }
.cg-pack-opt small { color: var(--ng-grey); }
.cg-pack-opt input { accent-color: var(--ng-gold); }

.cg-config__actions { display: flex; justify-content: space-between; align-items: center; gap: 14px;
  padding: 16px 22px; background: var(--ng-off-white); border-top: 1px solid var(--ng-line); flex-wrap: wrap; }
.cg-config__extras { color: var(--ng-grey); font-size: .9rem; }
.cg-config__foot { display: flex; justify-content: space-between; gap: 12px; margin: 32px 0 60px; flex-wrap: wrap; }
.btn.is-disabled { opacity: .5; pointer-events: none; }

/* ==========================================================================
   MOBILE
   --------------------------------------------------------------------------
   Audited at 390px. Two things dominated the Phase 2 pages: product grids
   fell to one card per row (so four products filled 1,742px), and the
   allergen/diet filter panel ran to 800px — two full screens of controls
   before a single product appeared. Both are fixed below.
   ========================================================================== */
@media (max-width: 700px) {

  /* --- Product grids: two per row ----------------------------------------
     minmax(min(250px, 100%),1fr) leaves room for exactly one column at 390px. A phone
     comfortably shows two cards side by side, which roughly halves the scroll
     and lets a shopper compare without paging up and down. */
  .card-grid, .grid--cards { grid-template-columns: repeat(2, 1fr); gap: .75rem; }
  .cg-card__body { padding: 10px 10px 12px; gap: 6px; }
  .cg-card__price { font-size: 1rem; }
  .cg-card__avail { font-size: .76rem; }
  .cg-card__add input { width: 100%; min-width: 0; }
  .cg-card__add { flex-wrap: wrap; gap: 6px; }
  .cg-card__add .btn { flex: 1 1 100%; }
  .card__namebar { font-size: .88rem; line-height: 1.3; }
  /* Only the first couple of flags — a stack of eight chips buries the price. */
  .cg-flaglist { gap: 4px; }
  .cg-flag { font-size: .66rem; padding: 2px 6px; }
  .cg-card__body .cg-flaglist .cg-flag:nth-child(n+3) { display: none; }

  /* --- The filter panel collapses ----------------------------------------
     The two flag zones are the bulk of it. They open on demand (see
     site.js, which sets `open` by viewport) so the catalogue is the first
     thing on screen, not the controls. */
  .cg-filters { padding: 12px; margin: 12px 0 16px; }
  .cg-filters__row { gap: 8px; }
  .cg-filters__search, .cg-filters select, .cg-filters .btn { flex: 1 1 100%; }
  .cg-filters__zones { grid-template-columns: 1fr; gap: 10px; margin-top: 10px; }
  .cg-zone { padding: 8px 10px; }
  .cg-chip { margin: 3px 4px 3px 0; padding: 0 12px; min-height: 44px; font-size: .84rem; }

  /* --- Headings and copy --------------------------------------------------
     The lede ran to seven lines before anything actionable. */
  .cg-catalogue h1, .cg-product h1 { font-size: 1.5rem; }
  .cg-catalogue .lede { font-size: .95rem; }
  .cg-promise { font-size: .84rem; padding: 7px 12px; margin-bottom: 12px; }
  .cg-crosssell { margin-top: 32px; padding: 20px; }

  /* --- Two-path block on the homepage ------------------------------------ */
  .cg-paths { padding: 34px 0; }
  .cg-paths__inner { padding: 0 16px; }
  .cg-path { padding: 20px 18px; }
  .cg-path p { font-size: .94rem; margin-bottom: 12px; }
  .cg-paths__lede { margin-bottom: 18px; }

  /* --- Single product page ------------------------------------------------ */
  .cg-product__layout { gap: 18px; }
  .cg-product__detail h1 { font-size: 1.25rem; }
  .cg-product__price { font-size: 1.4rem; margin: 8px 0 14px; }
  .cg-product__add { gap: 8px; }
  .cg-product__add input { width: 84px; }
  .cg-product__add .btn { flex: 1 1 auto; }

  /* --- Configurator -------------------------------------------------------
     One card per option was making each basket line a screen and a half. */
  .cg-config__head { padding: 12px 14px; }
  .cg-config__block { padding: 14px; }
  .cg-cards { grid-template-columns: repeat(2, 1fr); gap: 8px; }
  .cg-card-opt { padding: 10px; font-size: .88rem; }
  .cg-pack { grid-template-columns: 1fr; gap: 8px; }
  .cg-logo-preview { grid-template-columns: 1fr; gap: 12px; }
  .cg-logo-preview img { max-width: 200px; }
  .cg-config__actions { padding: 12px 14px; }
  .cg-config__actions .btn { flex: 1 1 100%; }
  .cg-config__foot .btn { flex: 1 1 100%; }
}

/* Small phones: one column of product cards reads better than two cramped ones
   once the card drops below about 150px wide. */
@media (max-width: 340px) {
  .card-grid, .grid--cards, .cg-cards { grid-template-columns: 1fr; }
}

/* Filter disclosure. On a large screen it is just a labelled block, so the
   summary marker is hidden and it reads as it always did; on a phone it is a
   real, tappable toggle (site.js sets `open` from the viewport). */
.cg-filters__disclosure > summary { list-style: none; cursor: pointer; }
.cg-filters__disclosure > summary::-webkit-details-marker { display: none; }
@media (min-width: 701px) {
  .cg-filters__disclosure > summary { display: none; }
}
@media (max-width: 700px) {
  .cg-filters__disclosure > summary {
    display: flex; align-items: center; justify-content: space-between;
    min-height: 44px; margin-top: 8px; padding: 0 12px;
    border: 1px solid var(--ng-line); border-radius: 8px;
    font-weight: 600; font-size: .9rem; background: var(--ng-off-white);
  }
  .cg-filters__disclosure > summary::after { content: "▾"; color: var(--ng-grey); }
  .cg-filters__disclosure[open] > summary::after { content: "▴"; }
}

/* ===== Pager ============================================================= */
.cg-pager { display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: 6px; margin: 28px 0 8px; }
.cg-pager__n { display: inline-flex; align-items: center; justify-content: center;
  min-width: 40px; min-height: 40px; padding: 0 10px; border-radius: 8px;
  border: 1px solid var(--ng-line); font-weight: 600; font-size: .9rem; }
.cg-pager__n:hover { border-color: var(--ng-gold); color: var(--ng-ink); }
.cg-pager__n.is-current { background: var(--ng-navy); color: var(--ng-white); border-color: var(--ng-navy); }
.cg-pager__gap { padding: 0 4px; color: var(--ng-grey); }
@media (max-width: 700px) { .cg-pager { gap: 4px; } .cg-pager__n { min-width: 36px; min-height: 40px; } }

/* ==========================================================================
   COMPONENT CARDS — uniform height regardless of title length
   --------------------------------------------------------------------------
   Component names vary from "Nozeco Prosecco 0.0 20cl" to "Alain Milliat Blanc
   de Blancs Chardonnay Sparkling 75cl". A title that wraps to two lines pushed
   everything below it down, so the price, availability and Add button sat at a
   different height on every card and the grid looked ragged.
   
   The fix is to stop the title influencing layout at all: the name area always
   occupies the SAME number of lines whether the title fills them or not, so
   every card in a row is identical and the images line up.
   ========================================================================== */

/* Rows stretch, so every card in a row is the height of the tallest. */
.cg-grid { align-items: stretch; }
.card--component {
  height: 100%;
  display: flex;
  flex-direction: column;
  background: var(--ng-white);
  border-radius: var(--ng-radius-lg);
  overflow: hidden;
  box-shadow: var(--ng-shadow-sm);
}

.card--component .card__link { display: flex; flex-direction: column; }

/* The image is a fixed square, so it never resizes to fill leftover space. */
.card--component .card__media {
  display: block; aspect-ratio: 1 / 1; overflow: hidden;
  background: var(--ng-bg); border-radius: 0;
}
.card--component .card__media img { width: 100%; height: 100%; object-fit: cover; }

/* The name bar reserves exactly two lines. A one-line title keeps the second
   line's space, a three-line title is clamped with an ellipsis — either way
   the height is identical on every card.

   The vertical padding is a variable because it appears twice: once as real
   padding and once as the allowance inside the reserved height. Hard-coding it
   in both places is how the clamp and the box end up disagreeing when someone
   tightens one and forgets the other.

   A product name is a caption, not a banner, so the gold reads as a rule under
   the photograph rather than a full solid block. It is an inset shadow rather
   than a border because under border-box a border would eat into the two lines
   the height calculation has reserved. */
.card--component .card__namebar {
  --cg-title-lines: 2;
  --cg-title-lh: 1.25;
  --cg-title-pad-y: .35rem;
  display: -webkit-box;
  -webkit-line-clamp: var(--cg-title-lines);
  -webkit-box-orient: vertical;
  overflow: hidden;
  height: calc(var(--cg-title-lines) * var(--cg-title-lh) * 1em + var(--cg-title-pad-y) * 2);
  padding: var(--cg-title-pad-y) .6rem;
  line-height: var(--cg-title-lh);
  font-size: .83rem;
  font-weight: 600;
  text-align: center;
  background: var(--ng-white);
  color: var(--ng-ink);
  box-shadow: inset 0 2px 0 var(--ng-gold);
  border-radius: 0;
}

/* The body fills the rest, and the Add row is pinned to the bottom so the
   buttons line up across the whole row. */
.cg-card__body { flex: 1; display: flex; flex-direction: column; gap: 8px; }
.cg-card__add { margin-top: auto; }

/* Availability wording also varies in length ("12 available for your date" vs
   "Available to order in for your date"), so it gets a reserved two lines too. */
.cg-card__avail {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; min-height: 2.4em; line-height: 1.2;
}

/* Flag chips are optional per component; reserving no space is fine, but they
   must not push the price around, so they sit in their own fixed-height row. */
.cg-card__body .cg-flaglist { min-height: 0; }

@media (max-width: 700px) {
  /* Still two reserved lines — two cards per row only line up if the phone
     reserves the same space the desktop does. */
  .card--component .card__namebar { --cg-title-lines: 2; --cg-title-pad-y: .3rem; font-size: .76rem; padding-inline: .5rem; }
  .cg-card__avail { min-height: 2.2em; font-size: .74rem; }
}

/* ===== Product gallery ===================================================
   A component can be photographed several times (angle, packaging, detail).
   The main image cross-fades rather than cutting, because a hard swap between
   two similar photographs reads as a glitch rather than a change.
   ======================================================================== */
.cg-product__gallery { display: flex; flex-direction: column; gap: 10px; }
.cg-product__main { width: 100%; height: auto; display: block; transition: opacity .16s ease; }
.cg-product__main.is-swapping { opacity: 0; }

.cg-product__thumbs { display: flex; gap: 8px; flex-wrap: wrap; }
.cg-product__thumb {
  width: 72px; height: 72px; object-fit: cover; border-radius: 10px;
  cursor: pointer; background: var(--ng-bg);
  border: 2px solid transparent; outline-offset: 2px;
  transition: border-color .18s ease, transform .18s ease, opacity .18s ease;
  opacity: .72;
}
.cg-product__thumb:hover { opacity: 1; transform: translateY(-2px); }
.cg-product__thumb.is-active { border-color: var(--ng-gold); opacity: 1; }
.cg-product__thumb:focus-visible { outline: 2px solid var(--ng-gold); }

/* Respect a reduced-motion preference: switch instantly, no fade or lift. */
@media (prefers-reduced-motion: reduce) {
  .cg-product__main, .cg-product__thumb { transition: none; }
  .cg-product__main.is-swapping { opacity: 1; }
  .cg-product__thumb:hover { transform: none; }
}

@media (max-width: 700px) {
  .cg-product__thumb { width: 60px; height: 60px; }
  .cg-product__thumbs { gap: 6px; }
}

/* Catalogue cards: same square-but-never-cropped treatment as the builder.
   See the note in hamper.css — cover was cutting the top and bottom off tall
   products and cropping each one differently. */
.card--component .card__media {
  background: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 8px;
}
.card--component .card__media img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: center;
}
.card--component .card__media img.is-generated { object-fit: cover; }
.card--component .card__media:has(img.is-generated) { padding: 0; }
