/* ==========================================================================
   Notting Hill Vape — category page
   NHV-10 - Category Page

   Depends on the design tokens in ../nhv.css.
   ========================================================================== */

.nhv-cat-head { margin: 0 0 20px; }

.nhv-cat-title {
  margin: 0 0 16px;
  font-family: var(--nhv-font-display);
  font-size: 22px;
  font-weight: var(--nhv-fw-semi);
  color: var(--nhv-ink);
}

.nhv-cat-intro { margin-bottom: 20px; }
.nhv-cat-intro-image { float: left; max-width: 140px; height: auto; margin: 0 16px 12px 0; }
.nhv-cat-intro-text { font-size: var(--nhv-fs-base); line-height: 1.6; color: var(--nhv-ink); }
.nhv-cat-intro::after { content: ''; display: block; clear: both; }

/* --- Child categories ----------------------------------------------------- */

/* --- Child categories ----------------------------------------------------
   Cards, full container width, above the two-column row. The visible "Refine
   Search" heading is gone; the nav keeps an aria-label so it stays a named
   landmark. */

.nhv-cat-children { margin: 0 0 28px; }

.nhv-cat-children-grid {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 14px;
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Equal heights, always.

   The grid already stretches each <li> to the tallest in the row, but the <a>
   inside was sizing to its own content, so a one-line name gave a card 15px
   shorter than its two-line neighbours. The <li> becomes a flex container and
   the card fills it; the name area then takes up whatever slack is left, which
   is what keeps the bottom edges aligned however the names wrap. */
.nhv-cat-children-grid > li { display: flex; }

.nhv-cat-child {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  text-decoration: none;
  border: 1px solid var(--nhv-rule-warm);
  border-radius: var(--nhv-radius-sm);
  overflow: hidden;
  background: var(--nhv-cream-bright);
  transition: border-color 0.15s ease, transform 0.15s ease;
}
.nhv-cat-child:hover,
.nhv-cat-child:focus { border-color: var(--nhv-copper); }
.nhv-cat-child:focus-visible { outline: 2px solid var(--nhv-copper); outline-offset: 2px; }

/* The image is taken out of flow so the box keeps its 4:3 shape. Left in flow,
   a `height: 100%` image against an auto-height parent resolves to auto and the
   image's own proportions win — which made the box square instead of 4:3. */
.nhv-cat-child-media {
  position: relative;
  display: block;
  flex: 0 0 auto;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background-color: var(--nhv-navy-panel);
}
.nhv-cat-child-media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.nhv-cat-child-name {
  /* flex-grow is what equalises the cards: the name area absorbs the difference
     between a one-line and a two-line title. Centred both ways so a short name
     does not sit high in a tall box. */
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 10px 10px 12px;
  font-family: var(--nhv-font-display);
  font-size: var(--nhv-fs-small);
  font-weight: var(--nhv-fw-semi);
  line-height: 1.3;
  color: var(--nhv-navy);
  text-align: center;
}
.nhv-cat-child:hover .nhv-cat-child-name { color: var(--nhv-copper); }

/* No artwork: the card becomes one navy tile with the name set into it, rather
   than an empty grey box above a caption. That reads as a designed tile instead
   of a broken image — which matters, because with no category images in this
   catalogue it is currently what every card looks like. min-height keeps a row
   of these the same presence as a row with artwork (4:3 of a ~180px column). */
.nhv-cat-child.is-imageless {
  min-height: 135px;
  background-color: var(--nhv-navy-panel);
  background-image: linear-gradient(130deg, var(--nhv-navy-panel) 0%, var(--nhv-navy) 100%);
  border-color: var(--nhv-navy-border);
}
.nhv-cat-child.is-imageless .nhv-cat-child-name { color: var(--nhv-cream); }
.nhv-cat-child.is-imageless:hover { border-color: var(--nhv-copper); }
.nhv-cat-child.is-imageless:hover .nhv-cat-child-name { color: var(--nhv-cream-bright); }

@media (max-width: 1199px) { .nhv-cat-children-grid { grid-template-columns: repeat(4, 1fr); } }
@media (max-width: 767px)  { .nhv-cat-children-grid { grid-template-columns: repeat(3, 1fr); gap: 10px; } }
@media (max-width: 479px)  { .nhv-cat-children-grid { grid-template-columns: repeat(2, 1fr); } }

/* --- Toolbar --------------------------------------------------------------
   The view toggle, compare link, sort and limit. Given the same panel treatment
   as the sidebar modules so the page reads as one system: the live toolbar is
   unstyled, but this page now carries navy panels down its right side and an
   unbranded grey strip across the products looked like something core forgot.

   The live select ground is rgb(246,240,232) — which is --nhv-sand exactly — so
   the chips keep that and only the bar around them is new. */

.nhv-cat-toolbar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px 12px;
  padding: 10px 12px;
  margin-bottom: 18px;
  background-color: var(--nhv-navy-panel);
  background-image: linear-gradient(130deg, var(--nhv-navy-panel) 0%, var(--nhv-navy) 100%);
  border: 1px solid var(--nhv-navy-border);
  border-radius: var(--nhv-radius-sm);
}

/* --- View toggle --- */
/* Bootstrap's .btn-default is a white button with a #ccc border, which on the
   navy bar reads as two floating white squares. */
.nhv-cat-view { display: flex; gap: 1px; }
.nhv-cat-view .btn,
.nhv-cat-view .btn:focus {
  width: 32px;
  height: 32px;
  padding: 0;
  color: var(--nhv-cream);
  background: transparent;
  border: 1px solid var(--nhv-navy-border);
  border-radius: var(--nhv-radius-sm);
  box-shadow: none;
  transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.nhv-cat-view .btn:hover,
.nhv-cat-view .btn:active {
  color: var(--nhv-cream-bright);
  background: var(--nhv-copper);
  border-color: var(--nhv-copper);
}
.nhv-cat-view .btn:focus-visible { outline: 2px solid var(--nhv-copper); outline-offset: 2px; }

/* --- Compare --- */
/* --nhv-copper-text, not --nhv-copper: on this ground the copper measures
   4.27:1, which is AA-large only, and this is 12px text. copper-text is 5.67:1. */
.nhv-cat-compare {
  font-family: var(--nhv-font-display);
  font-size: var(--nhv-fs-small);
  color: var(--nhv-copper-text);
  text-decoration: none;
}
.nhv-cat-compare:hover,
.nhv-cat-compare:focus { color: var(--nhv-cream-bright); text-decoration: underline; }
.nhv-cat-compare:focus-visible { outline: 2px solid var(--nhv-copper); outline-offset: 2px; }

/* --- Sort and limit --- */
.nhv-cat-selects {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
}
.nhv-cat-label {
  margin: 0;
  font-family: var(--nhv-font-display);
  font-size: var(--nhv-fs-small);
  font-weight: var(--nhv-fw-semi);
  color: var(--nhv-cream);
  white-space: nowrap;
}
.nhv-cat-selects .form-control,
.nhv-cat-selects .form-control:focus {
  width: auto;
  height: 32px;
  padding: 0 26px 0 8px;
  font-family: var(--nhv-font-body);
  font-size: var(--nhv-fs-small);
  color: var(--nhv-navy);
  background-color: var(--nhv-sand);
  border: 1px solid var(--nhv-navy-border);
  border-radius: var(--nhv-radius-sm);
  box-shadow: none;
  /* The native arrow is drawn in the OS grey and sits oddly against the sand;
     appearance:none plus a chevron drawn in --nhv-copper keeps it on-palette.
     The right padding above reserves room for it. */
  -webkit-appearance: none;
  appearance: none;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath fill='%23A3795B' d='M1 1l5 5 5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 9px center;
  background-size: 10px 7px;
}
.nhv-cat-selects .form-control:focus-visible { outline: 2px solid var(--nhv-copper); outline-offset: 2px; }

@media (max-width: 767px) {
  .nhv-cat-selects { margin-left: 0; width: 100%; }
  .nhv-cat-selects .form-control { flex: 1 1 auto; }
}

/* --- Empty state ----------------------------------------------------------
   Shared by every listing: search with no matches, and specials with no offers
   running. Lives here rather than in blocks/search.css because it is not a
   search concern — it was named .nhv-search-empty until the specials page
   needed the same panel. */

.nhv-listing-empty {
  margin: 0 0 22px;
  padding: 18px;
  font-family: var(--nhv-font-body);
  font-size: var(--nhv-fs-base);
  color: var(--nhv-navy);
  background: var(--nhv-sand);
  border: 1px solid var(--nhv-rule-warm);
  border-radius: var(--nhv-radius-sm);
}

.nhv-listing-actions { margin: 0 0 24px; }

.nhv-listing-continue {
  display: inline-block;
  padding: 10px 22px;
  font-family: var(--nhv-font-display);
  font-size: var(--nhv-fs-small);
  font-weight: var(--nhv-fw-semi);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--nhv-cream-bright);
  background: var(--nhv-navy);
  border: 1px solid var(--nhv-navy);
  border-radius: var(--nhv-radius-sm);
  text-decoration: none;
  transition: background-color 0.15s ease;
}
.nhv-listing-continue:hover,
.nhv-listing-continue:focus { background: var(--nhv-navy-light); border-color: var(--nhv-navy-light); color: var(--nhv-cream-bright); text-decoration: none; }
.nhv-listing-continue:focus-visible { outline: 2px solid var(--nhv-copper); outline-offset: 2px; }

/* --- Product grid ---------------------------------------------------------
   CSS Grid, not Bootstrap columns. common.js swaps .product-grid/.product-list
   on each card for the view toggle, so a list item is made to span every column
   instead — the toggle keeps working with no change to core JS. */

.nhv-products {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 20px;
  margin: 0 0 20px;
}
.nhv-products > .product-layout { width: auto; padding: 0; float: none; }
.nhv-products > .product-list { grid-column: 1 / -1; }

/* The container keeps Bootstrap's `row` class, whose clearfix `:before`/`:after`
   are display:table. In a float layout they are invisible, but a grid container
   turns every pseudo-element into a grid item, so `:before` was taking the first
   cell and shunting the whole first row one column to the right. The negative
   row margins are already overridden above; this removes the other half. */
.nhv-products::before,
.nhv-products::after { content: none; }

/* The card was borderless, so on a white page a product with a white-background
   photograph had no edge at all and the grid read as a loose scatter of images.
   A warm hairline and a shallow shadow give each one a boundary without turning
   the listing into a set of heavy boxes.

   --nhv-rule-warm is the theme's hairline on light grounds, already used on the
   meta block and every panel; the shadow is tinted with the navy rather than
   black so it sits in the same family as everything else. */
.nhv-products .product-thumb {
  display: flex;
  flex-direction: column;
  height: 100%;
  border: 1px solid var(--nhv-rule-warm);
  box-shadow: 0 1px 3px rgba(16, 47, 66, 0.07);
  overflow: hidden;
  border-radius: var(--nhv-radius-sm);
  transition: box-shadow 0.15s ease, border-color 0.15s ease;
}

.nhv-products .product-thumb:hover {
  border-color: var(--nhv-copper);
  box-shadow: 0 2px 8px rgba(16, 47, 66, 0.12);
}

.nhv-products .image {
  position: relative;
  background: var(--nhv-white);
  padding: 10px;
}
.nhv-products .image img {
  display: block;
  width: 100%;
  height: auto;
  /* Reserved square box, so a missing or slow image cannot drag the caption out
     of line with its neighbours — the same guard used on the other grids. */
  aspect-ratio: 1 / 1;
  object-fit: contain;
}

 /* The base badge stays copper so a future NEW / LOW STOCK label has somewhere
    to sit; only Sale takes the red, via a modifier rather than by matching on the
    word, which would break in any other language. */
.nhv-product-badge {
  position: absolute;
  top: 10px;
  right: 10px;
  padding: 3px 9px;
  background: var(--nhv-copper);
  color: var(--nhv-cream-bright);
  font-family: var(--nhv-font-display);
  font-size: var(--nhv-fs-micro);
  font-weight: var(--nhv-fw-semi);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  border-radius: var(--nhv-radius-sm);
}

/* The dark caption panel — the defining feature of the live card.

   `flex: 0 0 auto`, not `1 1 auto`. Growing the caption made it absorb all the
   card's spare height: it measured 200px around 87px of content, leaving ~113px
   of dead espresso under every price. Sizing to content with a 100px floor keeps
   short and long captions the same height (the name is already clamped to two
   lines) and drops the card from 455px to 375px. */
.nhv-products .caption {
  /* GROWS, and that is the point. The card is a flex column stretched to the
     row's height by `height: 100%`, so whenever the tallest card in a row is
     taller than this one the difference had nowhere to go and collected as bare
     card background underneath the buttons — 22px of it, measured, on every
     card in the row.

     Letting the caption take the slack puts the button group hard against the
     bottom edge and fills the gap with the caption's own texture rather than
     white. Growing the IMAGE instead would stretch the product photograph, and
     `margin-top: auto` on the buttons would move the same gap above them where
     it would show as a white band — worse, not better. */
  flex: 1 1 auto;
  min-height: 100px;
  padding: 14px 12px 12px;
  text-align: center;

  /* The metal texture, bare.

     background-color is the asset's own mean (#434343 — measured, and the same
     value NHV-05 landed on), so the panel carries the right weight from first
     paint and never flashes a light box while the JPEG loads.

     ACCESSIBILITY NOTE: an espresso scrim used to sit over this. It was removed
     on request. Without it --nhv-taupe (the product name) measures 2.99:1 against
     the texture's brightest pixels — below the 4.5:1 AA needs at 15px. The price
     in --nhv-sand is unaffected at 4.78:1. If the name is ever moved to
     --nhv-sand this comment can go with it. */
  background-color: var(--nhv-metal-ground);
  background-image:
    url('../../../../../../image/catalog/home-page/bg-hp-block.jpg');
  background-size: cover;
  background-position: center center;
  background-repeat: no-repeat;
}

.nhv-product-name {
  margin: 0 0 8px;
  font-family: var(--nhv-font-body);
  font-size: 15px;
  font-weight: var(--nhv-fw-normal);
  line-height: 1.35;
  /* Two lines reserved and clamped, so every price in a row sits at the same
     height regardless of title length. */
  min-height: 2.7em;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.nhv-product-name a { color: var(--nhv-taupe); text-decoration: none; }
.nhv-product-name a:hover { color: var(--nhv-cream-bright); }

.nhv-products .caption .price {
  margin: 0;
  font-family: var(--nhv-font-body);
  font-size: 18px;
  font-weight: var(--nhv-fw-bold);
  color: var(--nhv-sand);
}
.nhv-products .caption .price-new { color: var(--nhv-gold); }
.nhv-products .caption .price-old {
  margin-left: 6px;
  font-size: var(--nhv-fs-small);
  font-weight: var(--nhv-fw-normal);
  color: var(--nhv-copper-text);
  text-decoration: line-through;
}
.nhv-products .caption .rating { margin-top: 6px; color: var(--nhv-copper-text); }

/* Description is for list view only; hidden on the grid card.

   Selectors here carry the `p` type and are scoped through .caption rather than
   written as a bare .nhv-product-desc. nhv.css clamps every non-price caption
   paragraph with `.product-thumb .caption > p:not(.price)` — (0,3,1), since
   :not() takes the specificity of its argument and `p` adds a type — which
   outranks a lone class and would leave the description showing on the grid.
   Matching (0,3,1) and relying on load order (blocks/ load after nhv.css) hides
   it; the list-view rule then goes higher again to bring it back. */
.nhv-products .caption > p.nhv-product-desc { display: none; }
.nhv-products > .product-list .caption > p.nhv-product-desc {
  display: block;
  margin: 10px 0 0;
  font-size: var(--nhv-fs-base);
  line-height: 1.5;
  color: var(--nhv-taupe);
  text-align: left;
}
.nhv-products > .product-list .caption { text-align: left; }
/* The list title carries the row. In the grid it is 15px body text clamped to
   two lines, sized to sit quietly under a thumbnail; given a full row it was
   smaller than the price beneath it, which read as a caption rather than a
   heading.

   20px in the display face, which is the step between --nhv-fs-lead and the
   22px of .nhv-block-title — deliberately just below the block headings so it
   does not compete with the section it sits inside. The clamp and the reserved
   two-line height go with it: those keep GRID cards level with each other and
   have nothing to do here, where each row sizes itself. */
.nhv-products > .product-list .nhv-product-name {
  min-height: 0;
  -webkit-line-clamp: none;
  display: block;
  margin-bottom: 10px;
  font-family: var(--nhv-font-display);
  font-size: 20px;
  font-weight: var(--nhv-fw-semi);
  line-height: 1.3;
}

/* --- List view --------------------------------------------------------------
   A list card is a GRID, not the flex column a grid card is.

   Core lays list view out by floating the image left; this theme makes
   .product-thumb a flex column, so the float never applied and the image kept
   `width: 100%` with `aspect-ratio: 1/1`. At full row width that resolved to a
   square roughly 1,170px on a side — one product filling the viewport twice
   over, with the price somewhere below the fold. The toggle in the toolbar
   reaches it, so it was reachable and broken.

   Two columns: a fixed image rail and everything else. The image spans both
   rows so it stays beside the whole card, and the buttons sit under the caption
   rather than beside it, which keeps the primary action in the same relative
   place as in grid view. */
.nhv-products > .product-list .product-thumb {
  display: grid;
  grid-template-columns: 200px minmax(0, 1fr);
  grid-template-rows: 1fr auto;
}

/* --- Undoing core's float layout ---------------------------------------------
   stylesheet.css lays list view out by floating the image and pushing the
   caption clear of it. None of that belongs in a grid, and two of the three
   rules were visibly wrong rather than merely redundant:

     .product-list .product-thumb .image     { float: left; padding: 0 15px }
     .product-list .product-thumb .caption   { margin-left: 230px }
     .product-list .product-thumb .button-group { border-left: 1px solid #ddd }

   The margin was the one that showed. Inside a grid column it is no longer
   clearing anything — it just inset the caption 230px from its own column edge,
   so the dark panel started a third of the way across while the button row
   below it started at the column edge. Two left edges on the same side of the
   same card. */
.nhv-products > .product-list .image {
  grid-column: 1;
  grid-row: 1 / -1;
  display: flex;
  align-items: center;
  float: none;
}

/* The 100px floor is there to keep GRID cards level with each other; in a list
   row it only adds dead texture under the description. */
.nhv-products > .product-list .caption {
  grid-column: 2;
  grid-row: 1;
  min-height: 0;
  margin-left: 0;                       /* core's 230px float clearance */
  padding: 16px 18px;
}

.nhv-products > .product-list .caption .price { margin-top: 12px; }

/* The row spans the full column so the caption's ground continues behind it and
   the right-hand side reads as one panel — bounded and left-aligned, it left a
   band of bare card beside the buttons and the column looked like two unrelated
   surfaces stacked.

   The BUTTONS are what get bounded instead: flex-basis on the first stops "Add
   to Basket" stretching into an 800px bar, which is what a full-width group
   would otherwise produce on a 1400px row. */
.nhv-products > .product-list .button-group {
  grid-column: 2;
  grid-row: 2;
  border-left: 0;                       /* core's #ddd rule, wrong on texture */
  background-color: var(--nhv-metal-ground);
  background-image: url('../../../../../../image/catalog/home-page/bg-hp-block.jpg');
  background-size: cover;
  background-position: center center;
  background-repeat: no-repeat;
  padding: 0 12px 12px;
}

.nhv-products > .product-list .button-group button:first-child {
  flex: 0 1 300px;
}

@media (max-width: 600px) {
  /* Below this a 200px rail leaves too little for the copy, so the list row
     becomes the grid card it already knows how to be. */
  .nhv-products > .product-list .product-thumb {
    grid-template-columns: 1fr;
    grid-template-rows: auto auto auto;
  }
  .nhv-products > .product-list .image { grid-column: 1; grid-row: 1; }
  .nhv-products > .product-list .caption { grid-column: 1; grid-row: 2; }
  .nhv-products > .product-list .button-group { grid-column: 1; grid-row: 3; }
  .nhv-products > .product-list .button-group button:first-child { flex: 1 1 auto; }
}

/* --- Buttons -------------------------------------------------------------- */

.nhv-product-badge--sale { background: var(--nhv-sale-red); }

.nhv-products .button-group {
  display: flex;
  gap: 1px;
  border: 0;
  background: transparent;
}
.nhv-products .button-group button {
  border: 0;
  background: var(--nhv-copper);
  color: var(--nhv-cream-bright);
  font-family: var(--nhv-font-display);
  font-size: var(--nhv-fs-micro);
  font-weight: var(--nhv-fw-semi);
  text-transform: uppercase;

  /* "ADD TO BASKET" is three characters longer than "ADD TO CART" was, and at
     four cards per row that was enough to wrap it onto two lines and make the
     card taller than its neighbours. Three things keep it on one:
     nowrap forbids the break, the tighter letter-spacing and padding buy back
     the width, and min-width:0 lets the flex item shrink below its content
     width instead of forcing the row wider. */
  letter-spacing: 0.02em;
  white-space: nowrap;
  min-width: 0;
  padding: 10px 4px;
  cursor: pointer;
  transition: background var(--nhv-transition);
}
.nhv-products .button-group button:first-child { flex: 1 1 auto; }
.nhv-products .button-group button + button { flex: 0 0 auto; width: 40px; background: var(--nhv-navy-light); }
.nhv-products .button-group button:hover { background: var(--nhv-copper-muted); }
.nhv-products .button-group button:focus-visible { outline: 2px solid var(--nhv-copper); outline-offset: -2px; }

/* --- Footer --------------------------------------------------------------- */

/* --- Listing footer ---------------------------------------------------------
   Bookends .nhv-cat-toolbar. The toolbar opens the listing as a navy panel and
   the footer closes it with the same ground, border and radius, so the products
   sit between two matching rails instead of trailing off into a hairline.

   Shared by category, search, specials and the brand pages — all four use
   .nhv-cat-foot, so all four gain it. */
.nhv-cat-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--nhv-gutter);
  flex-wrap: wrap;

  /* Bottom margin as well as top. This is often the last element on the page
     before the site footer, and once it became a solid navy panel it butted
     straight into the footer's own dark ground — the two read as one block with
     a seam through it. It was not noticeable while this was a bare hairline. */
  margin: 18px 0 15px;
  padding: 10px 12px;
  background-color: var(--nhv-navy-panel);
  background-image: linear-gradient(130deg, var(--nhv-navy-panel) 0%, var(--nhv-navy) 100%);
  border: 1px solid var(--nhv-navy-border);
  border-radius: var(--nhv-radius-sm);
}

/* Was --nhv-ink-soft, which is a colour for light grounds and would have been
   near-invisible once the panel went navy. */
.nhv-cat-results {
  font-family: var(--nhv-font-body);
  font-size: var(--nhv-fs-small);
  color: var(--nhv-cream);            /* 10.72:1 */
}

/* --- Pagination -------------------------------------------------------------
   Bootstrap renders this as a bordered pill group with its own radii and
   margins; all of that is stripped and rebuilt so the numbers read as chips on
   the panel rather than a widget dropped onto it. */
.nhv-cat-foot .pagination {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin: 0;
  border-radius: 0;
}

.nhv-cat-foot .pagination > li { display: block; }

.nhv-cat-foot .pagination > li > a,
.nhv-cat-foot .pagination > li > span {
  display: block;
  float: none;
  min-width: 32px;
  padding: 6px 10px;
  font-family: var(--nhv-font-display);
  font-size: var(--nhv-fs-small);
  font-weight: var(--nhv-fw-semi);
  line-height: 1.4;
  text-align: center;
  color: var(--nhv-cream);
  background: transparent;
  border: 1px solid var(--nhv-navy-border);
  border-radius: var(--nhv-radius-sm);
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.nhv-cat-foot .pagination > li > a:hover,
.nhv-cat-foot .pagination > li > a:focus {
  color: var(--nhv-cream-bright);
  background: rgba(251, 243, 209, 0.10);
  border-color: var(--nhv-copper);
  text-decoration: none;
}

/* The current page inverts to the cream ground — the same move the active
   product tab makes, so "you are here" looks the same wherever it appears.

   Copper was the obvious accent and is not used: --nhv-cream-bright on
   --nhv-copper is 3.79:1 and these numerals are 12px, which needs 4.5:1.
   Inverting gives 13.68:1 and keeps the copper for the hover border. */
.nhv-cat-foot .pagination > li.active > span,
.nhv-cat-foot .pagination > li.active > a {
  color: var(--nhv-navy);
  background: var(--nhv-cream-bright);
  border-color: var(--nhv-cream-bright);
}

/* Bootstrap greys a disabled arrow against a light ground; on navy that reads
   as an enabled link. */
.nhv-cat-foot .pagination > li.disabled > span,
.nhv-cat-foot .pagination > li.disabled > a {
  color: rgba(251, 243, 209, 0.35);
  background: transparent;
  border-color: rgba(251, 243, 209, 0.12);
}

.nhv-cat-foot .pagination > li > a:focus-visible {
  outline: 2px solid var(--nhv-copper);
  outline-offset: 1px;
}

@media (max-width: 600px) {
  /* Stacked, and the numbers centred rather than shoved left, when the count
     and the pager can no longer share a line. */
  .nhv-cat-foot { justify-content: center; text-align: center; }
  .nhv-cat-foot .pagination { justify-content: center; }
}

/* --- Responsive ----------------------------------------------------------- */

@media (max-width: 1199px) { .nhv-products { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 991px)  { .nhv-products { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 600px)  {
  .nhv-products { grid-template-columns: repeat(2, 1fr); gap: 12px; }
  .nhv-cat-selects { margin-left: 0; width: 100%; }
  .nhv-products .button-group button span { display: none; }
  .nhv-products .button-group button:first-child { padding: 10px 0; }
}

/* ==========================================================================
   Sidebar modules — NHV-10
   ==========================================================================
   The live sidebar has no category module; it carries Filter Products and
   Newsletter. What is copied here is therefore the sidebar module *treatment*,
   not a module that exists upstream: a panel title over a plain list. The live
   titles compute to exactly our tokens already — #0F212D ground, #FBF3D1 text,
   Sora 700 22px, 1px #2A3B4B border, 15px padding — so .nhv-block-head matches
   them with nothing added. */

.nhv-side-module { margin-bottom: 25px; }
.nhv-side-module .nhv-block-head { margin-bottom: 0; }

.nhv-side-list,
.nhv-side-children {
  list-style: none;
  margin: 0;
  padding: 0;
}

/* The list reads as one continuous panel under the heading, so it takes the
   heading's side borders and closes with a bottom one. */
.nhv-side-list {
  border: 1px solid var(--nhv-rule-warm);
  border-top: 0;
}

.nhv-side-item > a,
.nhv-side-child > a {
  display: block;
  padding: 10px 14px;
  font-family: var(--nhv-font-body);
  font-size: var(--nhv-fs-base);
  line-height: 1.35;
  color: var(--nhv-navy);
  text-decoration: none;
  border-bottom: 1px solid var(--nhv-rule-warm);
  transition: background-color 0.15s ease, color 0.15s ease;
}

/* The last row in the panel would otherwise double up with the panel's own
   bottom border. */
.nhv-side-list > .nhv-side-item:last-child > a { border-bottom: 0; }
.nhv-side-item:last-child .nhv-side-children > .nhv-side-child:last-child > a { border-bottom: 0; }

.nhv-side-item > a:hover,
.nhv-side-child > a:hover,
.nhv-side-item > a:focus,
.nhv-side-child > a:focus {
  background: var(--nhv-sand);
  color: var(--nhv-copper);
}

.nhv-side-item > a:focus-visible,
.nhv-side-child > a:focus-visible {
  outline: 2px solid var(--nhv-copper);
  outline-offset: -2px;
}

/* The open category. Colour alone does not carry this — the template also sets
   aria-current — but it needs to be unmistakable, so the active parent picks up
   the heading's ground and reads as an extension of the panel title. */
.nhv-side-item.is-active > a {
  background: var(--nhv-navy-panel);
  color: var(--nhv-cream);
  font-weight: var(--nhv-fw-bold);
  border-bottom-color: var(--nhv-navy-border);
}
.nhv-side-item.is-active > a:hover { background: var(--nhv-navy); color: var(--nhv-cream-bright); }

/* Children sit on the sand ground so the open branch reads as one group, and are
   indented with a copper marker rather than core's `&nbsp;&nbsp;&nbsp;- `. */
.nhv-side-children { background: var(--nhv-sand); }
.nhv-side-child > a {
  position: relative;
  padding-left: 30px;
  font-size: var(--nhv-fs-small);
  color: var(--nhv-navy-light);
}
.nhv-side-child > a::before {
  content: '';
  position: absolute;
  left: 16px;
  top: 50%;
  width: 6px;
  height: 1px;
  background: var(--nhv-copper);
}
.nhv-side-child.is-active > a {
  color: var(--nhv-copper);
  font-weight: var(--nhv-fw-bold);
}
.nhv-side-child.is-active > a::before { width: 10px; left: 12px; }

@media (max-width: 767px) {
  .nhv-side-module { margin-bottom: 18px; }
}
