/* =============================================================
   HAVANA HOUSE — COMPONENTS
   Buttons, image slots, product cards, rails, tabs, tiles,
   strength meter.
   ============================================================= */

/* ---------------------------------------------------------------
   BUTTONS

   THE RULE lives here. Gold is 2.24:1 on white, so:
     .hh-btn--gold  = gold FILL with INK text (7.28:1). Legal on any
                      ground, because the text sits on the gold, not
                      the gold on the ground.
     .hh-btn--ink   = the primary action on a light ground.
     There is no gold-text-on-white button. There cannot be one.
   --------------------------------------------------------------- */
.hh-btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--hh-s2);
  padding: 13px var(--hh-s6);
  border: 1px solid transparent;
  border-radius: var(--hh-r);
  font-family: var(--hh-font-body);
  font-size: var(--hh-t-xs);
  font-weight: 500;
  letter-spacing: var(--hh-ls-btn);
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--hh-fast) var(--hh-ease),
              color var(--hh-fast) var(--hh-ease),
              border-color var(--hh-fast) var(--hh-ease);
}
.hh-btn--sm { padding: 9px var(--hh-s4); font-size: var(--hh-t-xxs); }
.hh-btn--block { width: 100%; }

.hh-btn--gold { background: var(--hh-gold-500); color: var(--hh-ink); }
.hh-btn--gold:hover { background: var(--hh-gold-400); }

.hh-btn--ink { background: var(--hh-ink); color: #fff; }
.hh-btn--ink:hover { background: var(--hh-ink-700); }

.hh-btn--ghost {
  background: transparent; color: var(--hh-ink);
  border-color: var(--hh-ink);
}
.hh-btn--ghost:hover { background: var(--hh-ink); color: #fff; }

.hh-btn--ghost-dark {
  background: transparent; color: #fff;
  border-color: rgba(255,255,255,.4);
}
.hh-btn--ghost-dark:hover { border-color: var(--hh-gold-500); color: var(--hh-gold-400); }

.hh-icon { flex: 0 0 auto; }

/* Every stroked chrome glyph carries the same 1px hairline whatever size it
   is drawn at. Without this the stroke scales with the icon — 1.13px on a
   30px basket, 0.75px on a 20px magnifier — and the six stop reading as one
   set. Away's run 0.93–1.17px; a flat 1 sits between them. No effect on the
   filled icons: they have stroke: none, so there is nothing to scale. */
.hh-icon > * { vector-effect: non-scaling-stroke; }
.hh-icon--sm { width: 14px; height: 14px; }
.hh-icon--lg { width: 28px; height: 28px; }

/* ---------------------------------------------------------------
   IMAGE SLOTS
   Every image on this page does not exist yet. The slot states its
   own dimensions so the shot list in notes/assets.md and the markup
   cannot drift apart.
   --------------------------------------------------------------- */
.hh-slot {
  aspect-ratio: var(--ratio, 4 / 5);
  width: 100%;
  background:
    repeating-linear-gradient(45deg,
      transparent 0 10px, rgba(35,31,32,.035) 10px 20px),
    var(--hh-surface-3);
  border: 1px solid var(--hh-line);
  display: flex; align-items: center; justify-content: center;
  padding: var(--hh-s4); text-align: center;
  overflow: hidden;
}
.hh-slot__label {
  font-size: var(--hh-t-xs);
  color: var(--hh-ink-500);
  letter-spacing: 0.02em;
  max-width: 22ch;
}
.hh-slot--dark {
  background:
    repeating-linear-gradient(45deg,
      transparent 0 10px, rgba(255,255,255,.035) 10px 20px),
    var(--hh-ink-800);
  border-color: var(--hh-line-dark);
}
.hh-slot--dark .hh-slot__label { color: var(--hh-ink-400); }

/* ---------------------------------------------------------------
   PRODUCT CARD
   The whole card is the link. Away's is not — its title is the only
   target, which is a 44px hit area inside a 400px tile.
   --------------------------------------------------------------- */
.hh-card {
  display: flex; flex-direction: column; height: 100%;
  text-decoration: none; color: inherit;
}
.hh-card__media { position: relative; background: var(--hh-surface-2); overflow: hidden; }

/* CONTAIN, not cover. Category tiles are scene photography and want cover;
   these are cut-outs, and cover would crop a square source to reach the box.

   THE GREY GROUND, AND HOW IT WORKS WITHOUT TRANSPARENT ASSETS.
   The supplied cut-outs have no alpha channel — the Villa Casdagli file is
   0% transparent, 91.9% opaque white. So a grey background alone would be
   invisible: a square opaque image in a square box covers it completely.

   mix-blend-mode: multiply solves it in one line. Multiply computes
   (image x backdrop) / 255, so white (255) returns the backdrop untouched
   and the white ground disappears, while the product — dark — barely moves:
   on #f6f6f6 everything is multiplied by 246/255, a 3.5% darkening.

   Two things to know before this is copied elsewhere:
     - It only works on a ground LIGHTER than the product. On any of the
       dark bands the product would be swallowed. A card that needs a dark
       ground needs a real alpha cut-out instead.
     - Near-white detail inside a product (chrome, glass, a pale band) goes
       grey rather than transparent. Wrong, but it degrades gracefully —
       a canvas knockout would punch holes straight through it.

   isolation: isolate keeps the blend inside this box, so the image blends
   against the media's own grey rather than whatever the section behind
   happens to be. */
.hh-card__media { isolation: isolate; }

.hh-card__img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: contain;
  mix-blend-mode: multiply;
  display: block;
  transition: transform var(--hh-slow) var(--hh-ease);
}
.hh-card:hover .hh-card__img { transform: scale(1.03); }
.hh-card__media .hh-slot { border: 0; }
.hh-card:hover .hh-card__media .hh-slot { background-color: var(--hh-gold-100); }

.hh-card__badge {
  position: absolute; top: var(--hh-s3); left: var(--hh-s3); z-index: 2;
  background: var(--hh-ink); color: #fff;
  font-size: var(--hh-t-xxs); font-weight: 500;
  letter-spacing: var(--hh-ls-wide); text-transform: uppercase;
  padding: 5px var(--hh-s3); border-radius: var(--hh-r-sm);
}
/* Final Hour is the one place a red is allowed, and it is a clearance
   mechanic, not a brand colour. 6.44:1 with white on it. */
.hh-card__badge--sale { background: var(--hh-danger); }

/* Product names run to one or two lines, which used to push the strength
   meter, price and format 24px out of step between neighbouring cards.
   Fixed at both ends:
     - the name reserves two lines, so the common case lines up tightly with
       no gap under the short titles;
     - the foot is pushed to the bottom, so a title that runs to three lines
       on a narrow card still cannot stagger the prices.
   Reserving alone would break on three lines; bottom-aligning alone would
   leave a hole under every one-line title. Together they hold either way. */
.hh-card__body {
  padding-top: var(--hh-s4);
  display: flex;
  flex-direction: column;
  flex: 1;
}
.hh-card__foot { margin-top: auto; }
.hh-card__region {
  font-size: var(--hh-t-xxs); letter-spacing: var(--hh-ls-wide);
  text-transform: uppercase; color: var(--hh-ink-500);
  margin: 0 0 var(--hh-s2);
}
/* Prompt, not Capstone. Capstone renders lowercase as small capitals, so a
   product name like "Not Another Cigar Subscription — August" becomes a
   three-line block of caps at 18px. Capstone is a display face; it carries
   headings and short labels, and anything that is a sentence or a product
   name is set in the body face. See notes/brief.md, "the fourth rule". */
.hh-card__name {
  font-family: var(--hh-font-body);
  font-size: var(--hh-t-h4);
  font-weight: 500;
  letter-spacing: 0;
  line-height: 1.32;
  min-height: calc(1.32em * 2);   /* two lines, so short titles do not pull the price up */
  margin: 0 0 var(--hh-s2);
}
.hh-card:hover .hh-card__name { text-decoration: underline; text-underline-offset: 3px; }
.hh-card__strength { margin-bottom: var(--hh-s2); }
.hh-card__price { font-weight: 500; color: var(--hh-ink); margin: 0 0 2px; }
.hh-card__meta { font-size: var(--hh-t-sm); color: var(--hh-ink-500); margin: 0; }

.hh-sec--dark .hh-card__name, .hh-sec--darkest .hh-card__name,
.hh-sec--dark .hh-card__price, .hh-sec--darkest .hh-card__price { color: #fff; }
.hh-sec--dark .hh-card__meta, .hh-sec--darkest .hh-card__meta,
.hh-sec--dark .hh-card__region, .hh-sec--darkest .hh-card__region { color: var(--hh-ink-300); }

/* ---------------------------------------------------------------
   STRENGTH
   Five squares, one hue. Never five colours — a green-to-red meter
   reads as a warning, which is not what "full bodied" means.
   --------------------------------------------------------------- */
.hh-strength { display: inline-flex; align-items: center; gap: var(--hh-s3); }
.hh-strength__pips { display: inline-flex; gap: 3px; }
.hh-strength__pip {
  width: 14px; height: 4px;
  background: var(--hh-strength-1);
  border-radius: 1px;
}
.hh-strength__pip.is-on { background: var(--hh-strength-4); }
.hh-strength__label {
  font-size: var(--hh-t-xxs); letter-spacing: 0.04em;
  color: var(--hh-ink-500);
}
.hh-strength--dark .hh-strength__pip { background: rgba(255,255,255,.16); }
.hh-strength--dark .hh-strength__pip.is-on { background: var(--hh-gold-500); }
.hh-strength--dark .hh-strength__label { color: var(--hh-gold-300); }

/* ---------------------------------------------------------------
   RAIL
   Real overflow scrolling with scroll-snap. Each item is rendered
   ONCE. The current site ships its carousel clones as markup — five
   products three times over — which is real bytes for a loop nobody
   asked for. With JavaScript off this is still a complete, scrollable
   list, and the track is focusable so it can be scrolled by keyboard.
   --------------------------------------------------------------- */
.hh-rail { position: relative; }
.hh-rail .hh-sechead { margin-bottom: var(--hh-s7); }
.hh-rail__track {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(240px, 1fr);
  gap: var(--hh-card-gap);
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: 0;
  padding-bottom: var(--hh-s4);
  /* The native bar is replaced by .hh-rail__progress below. */
  scrollbar-width: none;
}
.hh-rail__track::-webkit-scrollbar { display: none; }

/* ---------------------------------------------------------------
   RAIL PROGRESS

   Measured off Away's carousel: a 2px track in #b8b8b8 with a fill
   in their ink, scaled with scaleX() on a 0.3s transition.

   Ours scales to (scrollLeft + clientWidth) / scrollWidth — so it
   starts at whatever fraction is already visible and reaches full
   width exactly as the last card lands. It grows as you scroll
   rather than sliding, which is the part that reads well: the bar
   tells you how much of the row you have seen, not merely where a
   thumb happens to sit.

   It replaces the native scrollbar rather than sitting beside it,
   and it hides itself on a rail with nothing to scroll.
   --------------------------------------------------------------- */
.hh-rail__progress {
  height: 2px;
  background: var(--hh-line);
  margin-top: var(--hh-s2);
  overflow: hidden;
}
.hh-rail__progress span {
  display: block;
  height: 100%;
  background: var(--hh-ink);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform .3s var(--hh-ease);
}
.hh-rail.is-static .hh-rail__progress { display: none; }

/* On the dark bands the track cannot be --hh-line and the fill cannot
   be ink; both would vanish. */
.hh-sec--dark .hh-rail__progress,
.hh-sec--darkest .hh-rail__progress { background: var(--hh-line-dark); }
.hh-sec--dark .hh-rail__progress span,
.hh-sec--darkest .hh-rail__progress span { background: var(--hh-gold-500); }
.hh-rail__track > li { scroll-snap-align: start; min-width: 0; }
.hh-rail__track:focus-visible { outline-offset: 4px; }

/* Four across on desktop for a 4-item rail; the 8-item rails scroll. */
/* The buttons sit in the section head, beside the "view all" link, rather
   than being absolutely positioned into it — which collided with it. */
.hh-rail__nav { display: inline-flex; gap: var(--hh-s2); }
.hh-sechead__tools {
  display: flex; align-items: center; gap: var(--hh-s5);
  flex-wrap: wrap;
}
.hh-railbtn {
  width: 40px; height: 40px;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent;
  border: 1px solid var(--hh-line);
  border-radius: var(--hh-r-full);
  cursor: pointer; color: var(--hh-ink);
}
.hh-railbtn:hover { background: var(--hh-ink); color: #fff; border-color: var(--hh-ink); }
.hh-rail.is-static .hh-rail__nav { display: none; }

/* ---------------------------------------------------------------
   END CARD — the "view all" as the last cell of a scrolling rail

   Phone only, and the section-head link is hidden in exchange. On
   desktop that link is the better affordance and the favourites and
   events rails are static grids, so a fifth cell would change the
   column count. One affordance per breakpoint, never both.

   It fills the row height rather than matching the product image,
   so it reads as a destination at the end of the row instead of
   another product with a missing picture.
   --------------------------------------------------------------- */
.hh-rail__end { display: none; }

.hh-endcard {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--hh-s4);
  height: 100%;
  padding: var(--hh-s5);
  background: var(--hh-surface-2);
  text-align: center;
  text-decoration: none;
  color: var(--hh-ink);
  transition: background var(--hh-fast) var(--hh-ease);
}
.hh-endcard:hover { background: var(--hh-gold-100); }

/* On the warm band the grey end card is within two points of the section
   behind it and disappears. It goes white there so it still reads as a card. */
.hh-sec--warm .hh-endcard { background: var(--hh-surface); }
.hh-sec--warm .hh-endcard:hover { background: var(--hh-gold-100); }

.hh-endcard__icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 48px; height: 48px;
  border: 1px solid var(--hh-line);
  border-radius: var(--hh-r-full);
  background: var(--hh-surface);
  flex: 0 0 auto;
  transition: transform .2s ease;
}
.hh-endcard:hover .hh-endcard__icon { transform: translateX(3px); }

.hh-endcard__label {
  font-size: var(--hh-t-sm);
  font-weight: 500;
  letter-spacing: 0.02em;
  line-height: 1.35;
  max-width: 14ch;
}

/* The events rail sits on ink-950, where surface-2 would be a white slab. */
.hh-endcard--dark {
  background: var(--hh-ink-800);
  color: #fff;
  border: 1px solid var(--hh-line-dark);
  border-radius: var(--hh-r-lg);
}
.hh-endcard--dark:hover { background: var(--hh-ink-700); }
.hh-endcard--dark .hh-endcard__icon {
  background: transparent;
  border-color: var(--hh-gold-600);
  color: var(--hh-gold-500);
}
.hh-railbtn[disabled] { opacity: .3; cursor: default; }
.hh-railbtn[disabled]:hover { background: transparent; color: var(--hh-ink); border-color: var(--hh-line); }
.hh-sec--dark .hh-railbtn, .hh-sec--darkest .hh-railbtn {
  border-color: var(--hh-line-dark); color: #fff;
}
.hh-sec--dark .hh-railbtn:hover, .hh-sec--darkest .hh-railbtn:hover {
  background: var(--hh-gold-500); color: var(--hh-ink); border-color: var(--hh-gold-500);
}
.hh-sec--dark .hh-railbtn[disabled]:hover, .hh-sec--darkest .hh-railbtn[disabled]:hover {
  background: transparent; color: #fff; border-color: var(--hh-line-dark);
}

@media (min-width: 1000px) {
  /* A four-item rail has nowhere to scroll, so it lays out as a grid
     and its arrows disable themselves. */
  #rail-fav, #rail-events { grid-auto-columns: minmax(0, 1fr); overflow: visible; }
}

/* ---------------------------------------------------------------
   TABS — section B
   --------------------------------------------------------------- */
/* No rule under the strip. The full-width line was the conventional tab
   "shelf" — the rail the tabs sit on, interrupted by the active indicator —
   which earns its place when a tablist sits on the same ground as the panel
   below it and nothing else marks where the control ends.

   Neither holds here. The warm panel already delineates the section, so the
   rule was a second horizontal competing with the panel's own edge; and it
   ran the full container while the tabs occupy the left third, drawing a
   long line that points at nothing. Away has none either — just a border on
   the active tab. Ours keeps the gold indicator and drops the rail. */
.hh-tabs {
  display: flex; gap: var(--hh-s7);
  margin-bottom: var(--hh-s7);
  flex-wrap: wrap;
}
/* Prompt, not Capstone. "Shop by category" is an instruction, not a label —
   three words that read as a phrase — and Capstone sets it in caps, which
   made a row of three of them shout. It also breaks the fourth rule's own
   test: length, not importance. Away's are mixed case at 400 too.

   Sizes follow theirs: 1.5rem desktop, 1.125rem on a phone. */
.hh-tab {
  background: none; border: 0; cursor: pointer;
  padding: 0 0 var(--hh-s3);
  font-family: var(--hh-font-body);
  font-size: 1.5rem;
  font-weight: 400;
  letter-spacing: 0;
  line-height: 1.3;
  /* NOT ink-400. An inactive tab is text somebody has to read in order to
     decide to click it, and ink-400 was 2.96:1 on white and 2.76:1 on the
     panel — a plain AA failure on a control. ink-500 clears 4.5 on both. */
  color: var(--hh-ink-500);
  border-bottom: 2px solid transparent;
}
.hh-tab[aria-selected="true"] {
  color: var(--hh-ink);
  border-bottom-color: var(--hh-gold-500);
}
.hh-tab:hover { color: var(--hh-ink); }

/* ---------------------------------------------------------------
   TILES + BRANDS — section B panels
   --------------------------------------------------------------- */
/* The column count comes from the list length via --cols, so dropping a
   tile does not leave a hard-coded repeat(6) behind. */
.hh-tiles {
  display: grid;
  gap: var(--hh-card-gap);
  grid-template-columns: repeat(var(--cols, 6), minmax(0, 1fr));
}

/* ---------------------------------------------------------------
   TILE — name over the image, Away's arrangement

   Measured off their tile: title absolute at bottom left, flex row,
   6px gap to a 20px arrow, 12px padding (16px from tablet up),
   weight 500, 0.05em tracking, and the arrow on
   `transform .2s ease` moving `translate(3px)` on hover.

   ONE DELIBERATE ADDITION. Away has no scrim, no filter and no
   text-shadow — white type sits straight on the photograph, which
   works because they art-direct every shot. Ours arrive from
   suppliers and shoots we do not control, and white on a bright
   image is a contrast failure waiting to happen. The gradient below
   guarantees a floor: over even a pure white photograph the text
   still lands on about #3b3b3b, which is 11.2:1.
   --------------------------------------------------------------- */
.hh-tile { text-decoration: none; color: inherit; display: block; }
/* No radius. Away's tiles are square-cornered — measured 0px on the anchor,
   the wrapper and the image alike — and it agrees with our own note in
   tokens.css that a cigar band is a rectangle and so is a humidor. overflow
   stays hidden for the hover scale. */
.hh-tile__media {
  position: relative; display: block; overflow: hidden;
  background: var(--hh-surface-2);
}
.hh-tile__media::after {
  content: ""; position: absolute; inset: 0; pointer-events: none; z-index: 1;
  background: linear-gradient(180deg,
    rgba(16,16,15,0) 42%, rgba(16,16,15,.42) 72%, rgba(16,16,15,.82) 100%);
}
.hh-tile .hh-slot { border: 0; }
/* Real photography drops straight into the slot's footprint. object-fit
   means whatever crop arrives still fills an 8:9 tile without distorting. */
/* 1:1. Every source we hold crops less at square than at 8:9 — the landscape
   ones keep 6-8 points more width, and the square ones keep all of it. It
   also matches the shape the product catalogue supplies.

   Note this moves AWAY from Away, whose tiles are 3:4 portrait (their image
   wrapper is padding-top:133.333%). 8:9 was my own number, not theirs. The
   cost of square is a shorter, less prominent row; the gain is that nothing
   is cropped to fit a ratio the photography does not have. */
.hh-tile__img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  display: block;
  transition: transform var(--hh-slow) var(--hh-ease);
}
.hh-tile:hover .hh-tile__img { transform: scale(1.03); }
.hh-tile:hover .hh-slot { background-color: var(--hh-gold-100); }
.hh-tile__name {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
  display: flex; align-items: center; gap: 6px;
  padding: 12px;
  font-family: var(--hh-font-display);
  font-size: 1rem; font-weight: 500;
  letter-spacing: 0.05em; line-height: 1;
  color: #fff;
}
.hh-tile__arrow { width: 20px; height: 20px; flex: 0 0 auto; transition: transform .2s ease; }
.hh-tile:hover .hh-tile__arrow { transform: translateX(3px); }
@media (min-width: 768px) {
  .hh-tile__name { font-size: 1.125rem; padding: 16px; }
}

.hh-brands { display: grid; grid-template-columns: repeat(6, 1fr); gap: var(--hh-s4); }
.hh-brand {
  display: flex; flex-direction: column; align-items: center; gap: var(--hh-s3);
  padding: var(--hh-s4);
  border: 1px solid var(--hh-line);
  border-radius: var(--hh-r);
  text-decoration: none; color: inherit;
  transition: border-color var(--hh-fast) var(--hh-ease);
}
.hh-brand:hover { border-color: var(--hh-gold-600); }
.hh-brand__mark { width: 100%; }
.hh-brand__mark .hh-slot { border: 0; background-color: transparent; }
.hh-brand__name {
  font-size: var(--hh-t-sm); font-weight: 500; text-align: center;
  color: var(--hh-ink);
}
.hh-panel__foot { margin-top: var(--hh-s6); text-align: center; }

@media (max-width: 1100px) {
  .hh-tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .hh-brands { grid-template-columns: repeat(4, 1fr); }
}

/* ---------------------------------------------------------------
   PHONE — section B scrolls sideways instead of stacking

   Measured off Away at 375: the tabs are nowrap inside an
   overflow-x:auto strip, and each tile is 248px on a 375 viewport
   — 66% — with a 10px gap, the first one starting at the gutter.
   That leaves ~100px of the second tile showing, and that peek is
   the whole affordance: it is what tells you the row moves.

   Every one of these strips bleeds to the screen edge with a
   negative margin and pays the gutter back as padding, so the
   first item lines up with the body text while the scroll still
   runs edge to edge. scroll-padding-inline makes snapping land on
   the gutter rather than the true edge.
   --------------------------------------------------------------- */
@media (max-width: 700px) {
  .hh-bleed,
  .hh-tabs,
  .hh-tiles,
  .hh-brands {
    margin-inline: calc(var(--hh-gutter) * -1);
    padding-inline: var(--hh-gutter);
    overflow-x: auto;
    /* Without this the strips wobble vertically. Setting overflow-x to auto
       forces the OTHER axis out of `visible` and into `auto` — per spec, not
       a browser quirk — so each strip gained a scrollable axis it never
       asked for, and a pixel of rounding is enough to move it. */
    overflow-y: hidden;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: var(--hh-gutter);
    -webkit-overflow-scrolling: touch;
    /* A phone draws overlay scrollbars that fade; a Mac set to "always
       show" draws a permanent grey bar that sat on top of the tab rule and
       under the tiles, reading as a stray line. The peek is the affordance
       on these strips, so the bar is not doing any work. */
    scrollbar-width: none;
  }
  .hh-bleed::-webkit-scrollbar,
  .hh-tabs::-webkit-scrollbar,
  .hh-tiles::-webkit-scrollbar,
  .hh-brands::-webkit-scrollbar { display: none; }

  .hh-tabs {
    flex-wrap: nowrap;
    gap: var(--hh-s5);
    scroll-snap-type: none;
  }
  .hh-tab {
    font-size: 1.125rem;
    white-space: nowrap;
    flex: 0 0 auto;
    /* The -1px that lapped the container border is what the strip was
       scrolling in. The border is an inset shadow here, so it is not needed. */
    margin-bottom: 0;
  }

  .hh-tiles {
    display: grid;
    grid-template-columns: none;
    grid-auto-flow: column;
    /* vw, not %: a percentage here resolves against the grid's padded
       content box, which made the tiles 59% of the screen instead of 66%
       and shrank the peek. */
    grid-auto-columns: 66vw;
    gap: var(--hh-card-gap);
  }
  .hh-tiles > * { scroll-snap-align: start; }

  /* Twelve brands in one row would be four and a half screens of
     swiping. Two rows flowing in columns halves it. */
  .hh-brands {
    display: grid;
    grid-template-columns: none;
    grid-template-rows: repeat(2, auto);
    grid-auto-flow: column;
    grid-auto-columns: 38vw;
    gap: var(--hh-s3);
  }
  .hh-brands > * { scroll-snap-align: start; }

  .hh-rail__nav { display: none; }

  /* The end card replaces the section-head link on a phone. */
  .hh-rail__end { display: block; }
  .hh-rail .hh-sechead__tools .hh-seclink { display: none; }

  /* 48px under a 24px heading was too much once the link moved into the
     rail — Away runs 15px there. This lives here rather than in site.css
     because `.hh-rail .hh-sechead` is already set to s7 in this file, and
     at equal specificity the later stylesheet wins. */
  .hh-rail .hh-sechead { margin-bottom: var(--hh-s5); }

  /* Two cards and a sliver of the third, as Away does it.
     Ours were minmax(240px, 1fr) — 64% of a 375 viewport, so only one and a
     half showed and the row looked like it had almost nothing in it.

     Two things make it work. The track bleeds to the screen edge and pays
     the gutter back as padding, so the third card can peek INTO the gutter
     rather than being clipped at the content box. And the column is sized so
     exactly two cards plus their gap fill the content width: at 375 that is
     (343 - 20) / 2 = 161.5px, against Away's 162px, leaving the same 16px
     sliver showing. */
  .hh-rail__track {
    margin-inline: calc(var(--hh-gutter) * -1);
    padding-inline: var(--hh-gutter);
    scroll-padding-inline: var(--hh-gutter);
    grid-auto-columns: calc((100% - 2 * var(--hh-card-gap)) / 2);
  }

  /* Events are the exception. A product card carries a name and a price; an
     event card carries a venue, a title, a blurb, a price AND a button. At
     the two-up width its body had 114px of text: the venue ran to 2 lines,
     the title to 6 and the blurb to 9, for a 649px card of shredded text.

     One card and a clear peek instead. 85% of the content width is 291px at
     375, where the longest title — "Smoke & Equinox: Macanudo & The Lakes
     Distillery" — settles onto 2 lines, and 58px of the next card still
     shows so the row reads as scrollable. */
  #rail-events { grid-auto-columns: 85%; }
}

/* ---------------------------------------------------------------
   BREADCRUMB

   Lives here, not in product.css, because it is a component and not a page.
   It was written for the product page and the category page then used the
   same markup without the stylesheet that styled it — so the list rendered
   as two block <li> on separate lines with no separators, which is what an
   unstyled breadcrumb looks like. Anything two page types both render
   belongs in components.css.
   --------------------------------------------------------------- */
/* Top air only. The bottom gap belongs to whatever follows, because only
   that element knows how much a 48px page title or a product gallery wants
   above it. With padding on both sides this stacked against the next
   section's padding-top and produced 48px on the category page and 24px on
   the product page — two pages, same component, neither number chosen. */
.hh-crumbs { padding-block: var(--hh-s5) 0; }
.hh-crumbs ol {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--hh-s2);
  list-style: none; margin: 0; padding: 0;
  font-size: var(--hh-t-xs); color: var(--hh-ink-500);
}
.hh-crumbs li + li::before { content: "/"; margin-right: var(--hh-s2); opacity: .5; }
.hh-crumbs a { color: inherit; text-decoration: none; }
.hh-crumbs a:hover { color: var(--hh-ink); text-decoration: underline; }
.hh-crumbs [aria-current] { color: var(--hh-ink-700); }


/* ---------------------------------------------------------------
   ORDER PROGRESS (5 Nov 2026) — Amazon's stepper: a thick track, a
   dot per step, the done ones filled with a tick and the track
   filled up to them. Ordered · Age verified · Dispatched · Delivered.
   On the order complete page now, the account area later.
   --------------------------------------------------------------- */
.hh-progress { --hh-pg-track: var(--hh-ink-100); --hh-pg-fill: var(--hh-gold-500); --hh-pg-dot: 24px; --hh-pg-bar: 6px; display: flex; align-items: flex-start; margin: 0 0 36px; padding: 0; }
.hh-progress__step { position: relative; flex: 0 0 auto; display: flex; flex-direction: column; align-items: center; gap: 10px; text-align: center; max-width: 9em; }
/* the half-bars under a label, edge to dot centre, so the line runs dot centre to dot centre */
.hh-progress__step::before, .hh-progress__step::after { content: ""; position: absolute; top: calc((var(--hh-pg-dot) - var(--hh-pg-bar)) / 2); height: var(--hh-pg-bar); background: var(--hh-pg-track); }
.hh-progress__step::before { left: 0; right: 50%; }
.hh-progress__step::after { left: 50%; right: 0; }
.hh-progress__step:first-child::before, .hh-progress__step:last-child::after { display: none; }
.hh-progress__step.is-done::before, .hh-progress__step.is-next-done::after { background: var(--hh-pg-fill); }
.hh-progress__bar { flex: 1 1 0; height: var(--hh-pg-bar); margin-top: calc((var(--hh-pg-dot) - var(--hh-pg-bar)) / 2); background: var(--hh-pg-track); }
.hh-progress__bar.is-done { background: var(--hh-pg-fill); }
.hh-progress__bar.is-half { background: linear-gradient(to right, var(--hh-pg-fill) 50%, var(--hh-pg-track) 50%); }
.hh-progress__step.is-done::after { background: var(--hh-pg-fill); } /* the half-bar under a done label is always gold: the fill reaches at least halfway to the next dot */
.hh-progress__dot { position: relative; z-index: 1; display: grid; place-items: center; width: var(--hh-pg-dot); height: var(--hh-pg-dot); border-radius: 50%; background: var(--hh-pg-track); color: var(--hh-ink); }
.hh-progress__step.is-done .hh-progress__dot { background: var(--hh-pg-fill); color: #fff; }
.hh-progress__dot svg { width: 14px; height: 14px; }
.hh-progress__label { font-size: 13px; line-height: 1.3; color: var(--hh-ink-500); }
.hh-progress__step.is-done .hh-progress__label { font-weight: 600; color: var(--hh-ink); }
@media (max-width: 640px) { .hh-progress { margin-bottom: 28px; } .hh-progress__label { font-size: 12px; } }
