/* ============================================================================
   home-premium.css — Homepage-only premium layer
   ----------------------------------------------------------------------------
   Loaded from templates/index.tpl, AFTER theme.css and theme-premium.css.
   Everything is scoped to `#index` (the homepage <body id>), so no other page
   can be affected. Additive: delete this file and the homepage still works.

   theme.css carries ~1500 lines of hand-appended `!important` patches for the
   hero slider and the product grid (search its "NUCLEAR FIX" / "Pink Brand"
   blocks). Where a rule below needs to win against those, it is written with
   an `#index` prefix and `!important` deliberately — see OPERATIONS.md §4.
   ========================================================================== */

#index {
  /* Brand tokens — same palette as theme-premium.css, restated locally so this
     file stays self-contained. */
  --sk-pink: #d50075;
  --sk-pink-dark: #9e0056;
  --sk-pink-tint: #fef0f7;
  --sk-pink-line: #f0dce8;
  --sk-gold: #ffce54;
  --sk-gold-deep: #c08f22;
  --sk-ink: #1a0010;
  --sk-ink-soft: #5c4453;   /* 8.7:1 on white */
  --sk-ink-mute: #7d6473;   /* 5.3:1 on white */
  --sk-paper: #ffffff;
  --sk-wash: #fdfbfc;

  --sk-radius: 16px;
  --sk-radius-sm: 10px;
  --sk-radius-pill: 999px;

  /* Layered, low-opacity shadows — depth without the muddy grey halo */
  --sk-shadow-1: 0 1px 2px rgba(26, 0, 16, .04), 0 10px 28px rgba(213, 0, 117, .055);
  --sk-shadow-2: 0 2px 6px rgba(26, 0, 16, .06), 0 24px 52px rgba(213, 0, 117, .15);
  --sk-shadow-hero: 0 4px 12px rgba(26, 0, 16, .05), 0 30px 70px rgba(213, 0, 117, .12);

  --sk-ease: cubic-bezier(.22, .61, .36, 1);
  --sk-ease-out: cubic-bezier(.16, 1, .3, 1);
  --sk-dur: 320ms;
  --sk-dur-slow: 550ms;

  /* Fluid vertical rhythm: 48px at 360px wide → 88px at 1440px */
  --sk-section-y: clamp(3rem, 5.5vw, 5.5rem);
}

/* ============================================================================
   1. Page canvas + section rhythm
   ----------------------------------------------------------------------------
   theme.css pins `#content > section:first-of-type { margin: 0 !important }`,
   so ALL vertical rhythm here is padding, never margin.
   ========================================================================== */

#index .page-home {
  background: var(--sk-paper);
}

#index .page-home > section.featured-products,
#index .page-home > section.new-products,
#index .page-home > section.best-sellers-products,
#index .page-home > section.sk-band {
  padding-block: var(--sk-section-y) !important;
  position: relative;
}

/* Hairline separators instead of hard section edges. */
#index .page-home > section.new-products::before,
#index .page-home > section.best-sellers-products::before {
  content: '';
  position: absolute;
  inset-inline: max(1rem, calc((100% - 1296px) / 2));
  top: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--sk-pink-line) 18%, var(--sk-pink-line) 82%, transparent);
}

/* `mt-3` on the new/best-seller sections fights the rhythm above. */
#index .page-home > section.new-products.mt-3,
#index .page-home > section.best-sellers-products.mt-3 {
  margin-top: 0 !important;
}

/* Alternate tint so the page reads as distinct bands rather than one long scroll. */
#index .page-home > section.new-products {
  background: linear-gradient(180deg, var(--sk-wash) 0%, #fff 65%);
}

/* ============================================================================
   2. Hero slider
   ----------------------------------------------------------------------------
   The images are pre-composed 1920x720 artwork with baked-in text, so they keep
   `object-fit: contain` — cropping them would cut the typography. Everything
   here is chrome around the image: frame, controls, indicators.
   ========================================================================== */

#index #home-slider {
  padding-inline: clamp(0px, 2vw, 28px) !important;
  padding-top: clamp(12px, 1.6vw, 22px) !important;
}

#index #home-slider .carousel.slide {
  max-width: 1600px !important;
  margin: 0 auto !important;
  border-radius: clamp(10px, 1.4vw, 20px) !important;
  box-shadow: var(--sk-shadow-hero) !important;
  overflow: hidden !important;
  isolation: isolate;
}

/* Entrance: the incoming slide settles from 1.02 → 1, so it never ends up
   cropped — the crop only exists mid-transition. */
#index #home-slider .carousel-item.active img {
  animation: sk-hero-settle 1200ms var(--sk-ease-out) both;
}

@keyframes sk-hero-settle {
  from { transform: scale(1.022); }
  to   { transform: scale(1); }
}

/* ---- Indicators ----------------------------------------------------------
   All three slides are light pink artwork with dark type running to the bottom
   edge, so bare white dots vanish and a dark scrim over the bottom just greys
   the design out. A translucent chip reads as a deliberate control on light or
   dark artwork alike and stops the dots colliding with the baked-in stats row. */
#index #home-slider .carousel-indicators {
  /* >=14px so the 44px hit area extended below each bar (see ::after) clears the
     carousel's `overflow: hidden` edge instead of being clipped to ~40px. */
  bottom: clamp(14px, 1.4vw, 22px) !important;
  inset-inline: 0;
  width: fit-content;
  margin: 0 auto !important;
  padding: 7px 12px !important;
  gap: 7px !important;
  z-index: 6 !important;
  align-items: center;
  justify-content: center;
  border-radius: var(--sk-radius-pill);
  background: rgba(255, 255, 255, .74);
  backdrop-filter: blur(12px) saturate(1.4);
  -webkit-backdrop-filter: blur(12px) saturate(1.4);
  box-shadow: 0 4px 16px rgba(26, 0, 16, .12);
}

#index #home-slider .carousel-indicators button {
  width: 26px !important;
  height: 4px !important;
  margin: 0 !important;
  padding: 0 !important;
  border: none !important;
  border-radius: var(--sk-radius-pill) !important;
  background: rgba(26, 0, 16, .24) !important;
  opacity: 1 !important;
  transition: width var(--sk-dur) var(--sk-ease), background var(--sk-dur) var(--sk-ease);
  /* 4px tall bar, but a 24px tall hit area (WCAG 2.5.8 target size). */
  position: relative;
}

/* The visible bar is 4px tall; this invisible extension gives it a 44px hit
   area so the control still satisfies the theme's >=44px touch convention. */
#index #home-slider .carousel-indicators button::after {
  content: '';
  position: absolute;
  inset: -20px -5px;
}

#index #home-slider .carousel-indicators button.active {
  width: 44px !important;
  background: linear-gradient(90deg, var(--sk-pink), var(--sk-gold)) !important;
}

#index #home-slider .carousel-indicators button:focus-visible {
  outline: 2px solid var(--sk-pink);
  outline-offset: 5px;
}

/* ---- Arrows ---- */
#index #home-slider .carousel-control-prev,
#index #home-slider .carousel-control-next {
  width: 46px !important;
  height: 46px !important;
  top: 50% !important;
  bottom: auto !important;
  transform: translateY(-50%);
  border-radius: 50% !important;
  background: rgba(255, 255, 255, .82) !important;
  backdrop-filter: blur(10px) saturate(1.3);
  -webkit-backdrop-filter: blur(10px) saturate(1.3);
  border: 1px solid rgba(255, 255, 255, .9) !important;
  box-shadow: 0 6px 20px rgba(26, 0, 16, .16) !important;
  opacity: 0 !important;
  z-index: 6 !important;
  transition: opacity var(--sk-dur) var(--sk-ease),
              background var(--sk-dur) var(--sk-ease),
              transform var(--sk-dur) var(--sk-ease);
}

#index #home-slider .carousel-control-prev { left: clamp(10px, 2vw, 28px) !important; }
#index #home-slider .carousel-control-next { right: clamp(10px, 2vw, 28px) !important; }

/* Reveal on hover for mice; always visible for touch/keyboard (see §11). */
@media (hover: hover) {
  #index #home-slider:hover .carousel-control-prev,
  #index #home-slider:hover .carousel-control-next {
    opacity: 1 !important;
  }

  #index #home-slider .carousel-control-prev:hover,
  #index #home-slider .carousel-control-next:hover {
    background: var(--sk-pink) !important;
    transform: translateY(-50%) scale(1.08);
  }

  #index #home-slider .carousel-control-prev:hover .carousel-control-prev-icon,
  #index #home-slider .carousel-control-next:hover .carousel-control-next-icon {
    filter: brightness(0) invert(1) !important;
  }
}

#index #home-slider .carousel-control-prev:focus-visible,
#index #home-slider .carousel-control-next:focus-visible {
  opacity: 1 !important;
  outline: 3px solid var(--sk-pink);
  outline-offset: 3px;
}

#index #home-slider .carousel-control-prev-icon,
#index #home-slider .carousel-control-next-icon {
  width: 16px !important;
  height: 16px !important;
  transition: filter var(--sk-dur) var(--sk-ease);
}

/* ============================================================================
   2b. Native phone hero (.sk-hero — built by home-premium.js)
   ----------------------------------------------------------------------------
   The slides are 1920x720 composed artwork with the headline, stats and CTA
   baked in as pixels. Cropping them to the text column made phones legible, but
   the layout was still drawn for a landscape frame — and no crop fixes the real
   gaps: every slide carries alt="", so the hero says NOTHING to a screen reader
   or a search engine, and its call to action is a picture of a button.

   Below 768px the artwork is replaced by real DOM built from the same words.
   Crisp at any density, selectable, translatable, and the CTA is a genuine
   target. The slide's own photography is kept as a band underneath, cropped out
   of the original artwork by project-docs/tools/generate-mobile-slides.sh.

   Self-healing, same as the <picture> map: home-premium.js keys off the slide's
   image filename, so an unknown slide gets no block and falls back to the
   cropped image. Desktop is untouched at every width.

   THE COPY IS TRANSCRIBED FROM THE ARTWORK AND DOES NOT READ FROM IT. Replace a
   slide in the back office and this text goes stale — see THEME.md section 6.
   ========================================================================== */

/* Desktop keeps the artwork, but the block stays in the accessibility tree
   rather than being display:none — every slide ships alt="" and the link has no
   name, so this is the hero's only text alternative. Bootstrap marks inactive
   slides aria-hidden, so only the visible one is announced. The photo-band
   background-images are declared inside the phone media query below, so nothing
   extra is fetched here. */
#index .sk-hero {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

@media (max-width: 767.98px) {
  /* Hand the whole frame over to the native block. */
  #index #home-slider .carousel-item.sk-has-hero picture,
  #index #home-slider .carousel-item.sk-has-hero img {
    display: none !important;
  }

  #index #home-slider .carousel-item.sk-has-hero,
  #index #home-slider .carousel-item.sk-has-hero .carousel-link,
  #index #home-slider .carousel-item.sk-has-hero .carousel-content {
    display: block !important;
    width: 100%;
    margin: 0 !important;
    padding: 0 !important;
  }

  #index .sk-hero {
    position: relative;
    width: auto;
    height: auto;
    margin: 0;
    overflow: hidden;
    clip: auto;
    white-space: normal;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 1.25rem;
    /* !important because theme.css carries `#home-slider * { padding-bottom: 0
       !important; margin-bottom: 0 !important }` in its "Last resort - force
       zero gap" block. A universal !important beats any specificity, so every
       bottom pad inside the slider silently collapses without this — which is
       what dropped the CTA onto the indicators. */
    padding: 1.6rem 1.25rem 1.35rem !important;
    text-align: left;
    background:
      radial-gradient(26rem 18rem at 108% -8%, rgba(213, 0, 117, .1), transparent 62%),
      radial-gradient(22rem 16rem at -10% 108%, rgba(255, 206, 84, .16), transparent 62%),
      linear-gradient(170deg, #fff 0%, var(--sk-pink-tint) 100%);
    position: relative;
    overflow: hidden;
  }

  /* The "1978" device the rest of the page uses, at a size that stays a corner
     accent instead of sitting behind the headline. */
  #index .sk-hero::before {
    content: '1978';
    position: absolute;
    top: -14px;
    right: -6px;
    font-family: 'Playfair Display', Georgia, serif;
    font-size: 86px;
    font-weight: 700;
    line-height: 1;
    color: rgba(213, 0, 117, .05);
    font-variant-numeric: lining-nums;
    pointer-events: none;
  }

  #index .sk-hero > * { position: relative; z-index: 1; }

  /* Thin brand rule across the top edge — the same device the product cards
     use, so the hero reads as part of the page rather than a pasted-in banner. */
  #index .sk-hero::after {
    content: '';
    position: absolute;
    inset-inline: 0;
    top: 0;
    height: 3px;
    background: linear-gradient(90deg, var(--sk-pink), var(--sk-gold));
    z-index: 2;
  }

  /* Matched to the "Since 1978" pill on the .semsons-section block below, so the
     two badges on the same page are one component: 10px / 600 / 2px tracking /
     6px 16px / 30px radius, title case rather than uppercase.

     `padding` needs !important. theme.css's `#home-slider * { padding-bottom: 0
     !important }` was zeroing the bottom half, which is what made this pill look
     wrong: it computed to `6.08px 13.6px 0px`, so the text sat hard against the
     bottom edge and the badge was 17px tall against the reference's 27px. */
  #index .sk-hero__eyebrow {
    display: inline-block;
    padding: 6px 16px !important;
    border-radius: 30px;
    background: var(--sk-pink);
    color: #fff;
    font-size: 10px;
    font-weight: 600;
    line-height: 15px;
    letter-spacing: 2px;
    text-transform: none;
    box-shadow: 0 6px 16px rgba(213, 0, 117, .25);
  }

  /* theme.css's "Mobile Hero Fix" block sets `#home-slider .carousel p` to
     `font-size: 13px !important` — specificity (1,1,1) plus !important — which
     silently rendered this display headline at body size. Hence !important here;
     see THEME.md section 6. */
  #index .sk-hero__title {
    font-family: 'Playfair Display', Georgia, serif;
    font-size: clamp(1.6rem, 1.05rem + 2.4vw, 2.15rem) !important;
    font-weight: 600;
    line-height: 1.12 !important;
    letter-spacing: -.015em;
    color: var(--sk-ink);
    margin: 0;
    text-wrap: balance;
  }

  #index .sk-hero__title em {
    font-style: italic;
    color: var(--sk-pink);
    /* The gold swipe under the accent word, as on the desktop artwork. */
    background: linear-gradient(transparent 68%, rgba(255, 206, 84, .55) 68%);
  }

  #index .sk-hero__copy {
    font-size: .875rem !important;
    line-height: 1.68 !important;
    color: var(--sk-ink-soft);
    margin: 0;
    max-width: 34ch;
  }

  /* ---- stat row ---- */
  #index .sk-hero__stats {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem 1.15rem;
    margin: .15rem 0 0;
    padding: 0;
    list-style: none;
  }

  #index .sk-hero__stats li {
    padding-left: .75rem;
    border-left: 2px solid var(--sk-gold);
  }

  #index .sk-hero__stats b {
    display: block;
    font-family: 'Playfair Display', Georgia, serif;
    font-size: 1.25rem;
    font-weight: 700;
    line-height: 1.1;
    color: var(--sk-pink);
    font-variant-numeric: lining-nums tabular-nums;
  }

  #index .sk-hero__stats span {
    font-size: .5625rem;
    font-weight: 600;
    letter-spacing: .13em;
    text-transform: uppercase;
    color: var(--sk-ink-mute);
  }

  /* ---- chip / award rows ---- */
  #index .sk-hero__rows {
    display: flex;
    flex-direction: column;
    gap: .4rem;
    width: 100%;
    margin: 0;
    padding: 0;
    list-style: none;
  }

  #index .sk-hero__rows li {
    display: flex;
    align-items: flex-start;
    gap: .6rem;
    padding: .55rem .7rem;
    background: rgba(255, 255, 255, .8);
    border: 1px solid var(--sk-pink-line);
    border-radius: 10px;
  }

  #index .sk-hero__rows svg {
    flex: 0 0 auto;
    width: 15px;
    height: 15px;
    margin-top: 1px;
    padding: 3px;
    box-sizing: content-box;
    border-radius: 50%;
    background: var(--sk-pink);
    color: #fff;
    stroke: currentColor;
    fill: none;
    stroke-width: 2.6;
    stroke-linecap: round;
    stroke-linejoin: round;
  }

  #index .sk-hero__rows b {
    display: block;
    font-size: .75rem;
    font-weight: 600;
    line-height: 1.35;
    color: var(--sk-ink);
  }

  #index .sk-hero__rows span {
    display: block;
    font-size: .625rem;
    color: var(--sk-ink-mute);
    letter-spacing: .02em;
  }

  /* ---- photography band ---- */
  #index .sk-hero__shot {
    display: block;
    width: 100%;
    aspect-ratio: 5 / 3;
    /* At 5:3 the band grows with the viewport — it pushed the whole hero to
       766px tall at 767px wide. Capped, `background-size: cover` just crops a
       little rather than letting the hero swallow the fold. */
    max-height: 280px;
    margin-top: .2rem;
    border-radius: 12px;
    background-color: #fdf3f8;
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    box-shadow: 0 8px 22px rgba(26, 0, 16, .09);
  }

  /* Slide 2 carries four short chips; stacked they ran 177px and squeezed every
     other gap on that slide. Two-up they read as a spec block and the slide
     lands close to the other two. Slide 3's award names are far too long for
     half-width, so they stay one per row. */
  #index .sk-hero--s2 .sk-hero__rows {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: .5rem;
  }

  #index .sk-hero--s2 .sk-hero__rows li {
    padding: .5rem .6rem;
  }

  #index .sk-hero--s2 .sk-hero__rows b { font-size: .6875rem; }
  #index .sk-hero--s2 .sk-hero__rows span { font-size: .5875rem; }

  #index .sk-hero--s1 .sk-hero__shot { background-image: url("../img/home-mobile/slide-1-photo.webp"); }
  #index .sk-hero--s2 .sk-hero__shot { background-image: url("../img/home-mobile/slide-2-photo.webp"); }
  #index .sk-hero--s3 .sk-hero__shot { background-image: url("../img/home-mobile/slide-3-photo.webp"); }

  /* ---- no call-to-action button ------------------------------------------
     Removed by request. The whole card is `<a class="carousel-link">`, so
     tapping anywhere on it still navigates to that slide's destination — the
     pill was redundant on a phone and cost about 60px of height. Press and
     keyboard feedback therefore land on the card itself. */
  #index .carousel-item.sk-has-hero .carousel-link:active .sk-hero {
    transform: scale(.995);
  }

  #index .carousel-item.sk-has-hero .carousel-link:focus-visible {
    outline: none;
  }

  #index .carousel-item.sk-has-hero .carousel-link:focus-visible .sk-hero {
    outline: 3px solid var(--sk-pink);
    outline-offset: -3px;
  }
}

/* ============================================================================
   3. "Where Quality Speaks" (ps_customtext → .semsons-section)
   ----------------------------------------------------------------------------
   Already the strongest block on the page. Refinements only: real touch
   targets on the Explore buttons, calmer card motion, tidier mobile grid.
   ========================================================================== */

#index .semsons-section {
  max-width: 1400px;
  margin-inline: auto !important;
}

/* theme.css sets .body to 300 weight at 14.5px in #6b7180 — technically 4.7:1
   on this panel, but a 300-weight face at that size reads washed out. Bumping
   to 400 and one step darker keeps the same layout and gains real legibility. */
#index .semsons-section .body {
  font-weight: 400 !important;
  color: #5a5f6e !important;
}

#index .semsons-section .body strong {
  font-weight: 600 !important;
  color: var(--sk-ink) !important;
}

#index .semsons-section .subtitle {
  color: #4c5162 !important;
}

#index .semsons-section .card {
  will-change: transform;
}

/* theme.css leaves `min-width: 340px` on the cards column. Inside a 320px phone
   the section's own padding leaves it about 272px, so the grid ran ~50px past
   the edge and was silently cut off by the section's `overflow: hidden` — no
   scrollbar, just missing content. */
@media (max-width: 767.98px) {
  #index .semsons-section .cards-col,
  #index .semsons-section .stats-col,
  #index .semsons-section .text-col {
    min-width: 0 !important;
  }
}

/* theme.css renders the "1978" watermark at 140px inside a 393px-wide section
   on phones, so it spans almost the full width and sits behind the heading and
   body copy instead of reading as a corner accent. Same 4% alpha, quarter the
   footprint. */
@media (max-width: 767.98px) {
  #index .semsons-section::before {
    font-size: 88px !important;
    top: -6px !important;
    right: -2px !important;
    line-height: 1 !important;
  }
}

/* ---- Cards: images, contrast and the Explore control ----------------------
   Measured before changing anything:
     .desc rendered #b8789a on a white card — 3.39:1, which fails WCAG AA for
       11px text. Now the brand's muted ink at 5.3:1.
     .body used #5a5f6e, a cool blue-grey sitting on a warm pink ground; the
       rest of the page uses the warm plum neutral.
     The product photo was 99x99 inside a 159x115 plate — the card was mostly
       empty space, which is what made it read as unfinished.
   theme.css pins several of these with !important, hence the matching flags. */

#index .semsons-section .body {
  font-size: .875rem !important;
  line-height: 1.72 !important;
  color: var(--sk-ink-soft) !important;
}

#index .semsons-section .subtitle {
  color: #4a3341 !important;
}

#index .semsons-section .card {
  padding: 12px !important;
  border: 1px solid var(--sk-pink-line) !important;
  box-shadow: var(--sk-shadow-1) !important;
}

/* A 4:3 plate with the photo filling it, rather than a fixed 120px box the
   image floated inside. */
#index .semsons-section .card .img-wrap {
  height: auto !important;
  aspect-ratio: 4 / 3;
  padding: 6px !important;
  margin-bottom: 10px !important;
  background: linear-gradient(178deg, #ffffff 0%, #fbf7f9 100%) !important;
  border-radius: 10px !important;
}

#index .semsons-section .card .img-wrap img {
  width: 100% !important;
  height: 100% !important;
  max-height: none !important;
  object-fit: contain !important;
}

#index .semsons-section .card .nm {
  font-size: .875rem !important;
  line-height: 1.3 !important;
  margin-bottom: 4px !important;
}

#index .semsons-section .card .desc {
  font-size: .6875rem !important;
  line-height: 1.45 !important;
  color: var(--sk-ink-mute) !important;
}

/* Four outlined pills in a small grid read as noise. A single tinted bar per
   card, full width and a real 44px target, reads as one control. */
#index .semsons-section .card .explore-btn {
  display: flex !important;
  width: 100%;
  /* !important: theme.css pins `min-height: 36px !important` on this below
     768px, which quietly held the tap target at 37px on a phone. */
  min-height: 44px !important;
  /* `margin-top: auto` pins the bar to the bottom of the card. Without it a
     two-line description ("Automated stone placement") pushed its button down
     and the two cards in a row no longer lined up. The grid already stretches
     cards in a row to equal height, so this is all that was missing. */
  margin: auto 0 0 !important;
  padding: 10px 14px !important;
  background: var(--sk-pink-tint) !important;
  border: 1px solid transparent !important;
  color: var(--sk-pink-dark) !important;
  font-size: 10.5px !important;
  letter-spacing: .12em;
  border-radius: 30px !important;
  transition: background-color .2s ease, color .2s ease;
}

@media (hover: hover) {
  #index .semsons-section .card:hover .explore-btn {
    background: var(--sk-pink) !important;
    border-color: var(--sk-pink) !important;
    color: #fff !important;
    transform: none !important;
    box-shadow: 0 8px 18px rgba(213, 0, 117, .24) !important;
  }
}

/* ---- Grid rhythm ---- */
#index .semsons-section .cards-col {
  gap: 12px !important;
}

@media (max-width: 767.98px) {
  #index .semsons-section .cards-col {
    gap: 10px !important;
    margin-top: 24px !important;
  }

  #index .semsons-section .card { padding: 10px !important; }
  #index .semsons-section .card .explore-btn { font-size: 10px !important; }
}

/* Very narrow phones: two columns still fit, but only just. */
@media (max-width: 359.98px) {
  #index .semsons-section .card { padding: 8px !important; }
  #index .semsons-section .card .nm { font-size: .8125rem !important; }
}

/* The card is fully covered by `a.card-link` (text-indent:-9999px), so the
   focus ring has to be drawn on the card itself when that link is focused. */
#index .semsons-section .card:focus-within {
  outline: 3px solid var(--sk-pink);
  outline-offset: 3px;
}

#index .semsons-section .card a.card-link:focus-visible {
  outline: none;
}

@media (hover: hover) {
  #index .semsons-section .card:hover {
    transform: translateY(-10px) !important;
    box-shadow: var(--sk-shadow-2) !important;
  }
}

/* ---- Two-column layout ------------------------------------------------------
   theme.css sizes the columns as `flex-basis: 45%` / `50%` with `max-width: 45%`
   on the text, and puts a FIXED 60px gap between them. 45 + 50 = 95%, so the pair
   only fits while the gap is under 5% of the content width — i.e. above roughly
   1385px. At every laptop width below that the flex line wrapped and the cards
   dropped underneath a half-width text column, leaving the right-hand half of
   the section empty. Measured side-by-side only at 1440; stacked at 1280, 1200,
   1100, 1024 and 992.

   `flex-basis: 0` fixes it properly: the gap is taken out first and whatever
   remains is split by the grow factors, so the pair fits at any width the
   min-widths allow (300 + 340 + gap). The 1.1 keeps the cards column slightly
   wider than the text, which is what the percentages were reaching for. */
@media (min-width: 992px) {
  #index .semsons-section {
    gap: clamp(32px, 3.5vw, 60px) !important;
  }

  #index .semsons-section .text-col {
    flex: 1 1 0 !important;
    max-width: none !important;
    min-width: 300px !important;
  }

  #index .semsons-section .cards-col {
    flex: 1.1 1 0 !important;
    min-width: 340px !important;
  }
}

/* Tablets: stack deliberately rather than wrapping by accident, so the cards
   get the full width instead of a cramped half. */
@media (min-width: 768px) and (max-width: 991.98px) {
  #index .semsons-section {
    flex-direction: column !important;
    gap: 32px !important;
  }

  #index .semsons-section .text-col,
  #index .semsons-section .cards-col {
    flex: 1 1 auto !important;
    width: 100%;
    max-width: none !important;
    min-width: 0 !important;
  }
}

/* ---- Entrance ---------------------------------------------------------------
   Pure CSS, plays on load, no JavaScript involved.

   The JS scroll-reveal deliberately skips anything above the fold (hiding
   something the visitor can already see and fading it back reads as a glitch),
   and it measures position at deferred-script time — before the images above
   have settled. The result here was inconsistent: `.text-col` picked up the
   class and the four cards never did, so the section had no entrance at all.

   This block sits directly under the hero, so it is on screen when the page
   arrives and a load-time animation is the honest choice. Being CSS-only it also
   cannot leave content invisible if a script fails, and it needs no `.sk-js`
   guard. Under `prefers-reduced-motion: reduce` the rules simply never apply, so
   everything renders plainly at full opacity. */

@media (prefers-reduced-motion: no-preference) {
  #index .semsons-section .text-col > *,
  #index .semsons-section .card {
    animation: sk-sq-in 640ms cubic-bezier(.16, 1, .3, 1) both;
  }

  #index .semsons-section .text-col > *:nth-child(1) { animation-delay:  40ms; }
  #index .semsons-section .text-col > *:nth-child(2) { animation-delay:  95ms; }
  #index .semsons-section .text-col > *:nth-child(3) { animation-delay: 150ms; }
  #index .semsons-section .text-col > *:nth-child(4) { animation-delay: 200ms; }
  #index .semsons-section .text-col > *:nth-child(5) { animation-delay: 245ms; }

  /* `.card-row` is `display: contents`, so the cards are grid items of
     `.cards-col` but still nth-children of their own row. */
  #index .semsons-section .card-row:nth-child(1) .card:nth-child(1) { animation-delay: 210ms; }
  #index .semsons-section .card-row:nth-child(1) .card:nth-child(2) { animation-delay: 280ms; }
  #index .semsons-section .card-row:nth-child(2) .card:nth-child(1) { animation-delay: 350ms; }
  #index .semsons-section .card-row:nth-child(2) .card:nth-child(2) { animation-delay: 420ms; }

  @keyframes sk-sq-in {
    from { opacity: 0; transform: translateY(16px); }
    to   { opacity: 1; transform: none; }
  }
}

/* ---- Hover ------------------------------------------------------------------
   Pointer devices only. THEME.md is explicit that :hover latches after a tap on
   a touchscreen and leaves the card stuck mid-transform, so every rule that
   moves something lives behind `@media (hover: hover)`; coarse pointers get the
   press state further down instead. */

/* Brand rule that wipes across the top edge — the same device the product
   miniatures use, so the two card types read as one family. `::before` is
   already taken by theme.css for its tint overlay, hence `::after`. */
#index .semsons-section .card::after {
  content: '';
  position: absolute;
  inset-inline: 0;
  top: 0;
  height: 3px;
  background: linear-gradient(90deg, var(--sk-pink), var(--sk-gold));
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 520ms cubic-bezier(.16, 1, .3, 1);
  z-index: 3;
  pointer-events: none;
}

#index .semsons-section .card .img-wrap img {
  transition: transform 620ms cubic-bezier(.22, .61, .36, 1) !important;
}

#index .semsons-section .card .nm {
  transition: color .25s ease;
}

#index .semsons-section .card .explore-btn .arrow {
  transition: transform .28s cubic-bezier(.22, .61, .36, 1);
}

@media (hover: hover) {
  #index .semsons-section .card:hover::after {
    transform: scaleX(1);
  }

  /* theme.css zooms to 1.1, which crops noticeably on a 4:3 plate and reads
     cheap. 1.06 is enough to register as a response. */
  #index .semsons-section .card:hover .img-wrap img {
    transform: scale(1.06) !important;
  }

  #index .semsons-section .card:hover .nm {
    color: var(--sk-pink) !important;
  }

  #index .semsons-section .card:hover .explore-btn .arrow {
    transform: translateX(5px);
  }

  #index .semsons-section .card:hover {
    border-color: var(--sk-pink) !important;
  }
}

/* ---- Touch --------------------------------------------------------------
   No hover to lean on, so the press has to carry the feedback. */
@media (hover: none), (pointer: coarse) {
  #index .semsons-section .card {
    transition: transform .14s ease, box-shadow .14s ease !important;
  }

  #index .semsons-section .card:active {
    transform: scale(.975) !important;
  }

  #index .semsons-section .card:active .explore-btn {
    background: var(--sk-pink) !important;
    color: #fff !important;
  }
}

/* ============================================================================
   4. Section headers (.sk-head — built by home-premium.js)
   ----------------------------------------------------------------------------
   CSS-only fallback: without JS the stock <h2 class="section-title"> and the
   footer "All products" button both stay exactly where the module put them,
   just restyled by the .section-title rules below.
   ========================================================================== */

#index .section-title {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: clamp(1.75rem, 1.15rem + 1.9vw, 2.6rem) !important;
  font-weight: 600;
  line-height: 1.12;
  letter-spacing: -.015em;
  color: var(--sk-ink) !important;
  font-variant-numeric: lining-nums;   /* Playfair defaults to old-style digits */
  margin: 0 !important;
  padding-bottom: 0 !important;
}

/* theme-premium.css draws a 56px gradient bar under every .section-title via
   ::after. Inside .sk-head the bar moves above the title as an eyebrow rule. */
#index .sk-head .section-title::after {
  display: none;
}

#index .sk-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1rem 2rem;
  margin-bottom: clamp(1.75rem, 3vw, 2.75rem);
}

#index .sk-head__text {
  min-width: 0;
  flex: 1 1 20rem;
}

#index .sk-head__rule {
  display: block;
  width: 48px;
  height: 3px;
  margin-bottom: 1rem;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--sk-pink), var(--sk-gold));
}

/* "All products" link, relocated from the section footer into the header. */
#index .sk-head__link.all-product-link {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  min-height: 44px;
  padding: .55rem 1.35rem !important;
  border: 1px solid var(--sk-pink-line) !important;
  border-radius: var(--sk-radius-pill) !important;
  background: var(--sk-paper);
  color: var(--sk-pink) !important;
  font-size: .8125rem !important;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  transition: background var(--sk-dur) var(--sk-ease),
              border-color var(--sk-dur) var(--sk-ease),
              color var(--sk-dur) var(--sk-ease),
              box-shadow var(--sk-dur) var(--sk-ease),
              transform var(--sk-dur) var(--sk-ease);
}

#index .sk-head__link.all-product-link .material-icons {
  font-size: 18px !important;
  transition: transform var(--sk-dur) var(--sk-ease);
}

@media (hover: hover) {
  #index .sk-head__link.all-product-link:hover {
    background: var(--sk-pink) !important;
    border-color: var(--sk-pink) !important;
    color: #fff !important;
    box-shadow: 0 10px 24px rgba(213, 0, 117, .28);
    transform: translateY(-2px);
  }

  #index .sk-head__link.all-product-link:hover .material-icons {
    color: #fff !important;
    transform: translateX(4px);
  }
}

#index .sk-head__link.all-product-link:focus-visible {
  outline: 3px solid var(--sk-pink);
  outline-offset: 3px;
}

/* The now-empty module footer that the link came out of. */
#index .sk-footer--empty {
  display: none;
}

/* ============================================================================
   5. Product grid
   ----------------------------------------------------------------------------
   The stock grid is `.row` + `col-xl-3`, so a section holding 1–2 products
   parks them hard left with ~1000px of dead space beside them — which is
   exactly what "New products" and "Best Sellers" look like today. A centred
   flex track keeps a short row looking deliberate and still fills a long one.
   ========================================================================== */

#index .page-home .products.row {
  display: flex !important;
  flex-wrap: wrap;
  justify-content: center;
  align-items: stretch;
  gap: clamp(14px, 1.6vw, 28px);
  margin: 0 !important;
  --bs-gutter-x: 0;
  --bs-gutter-y: 0;
}

#index .page-home .products.row > .product-miniature {
  flex: 0 1 clamp(240px, 22vw, 310px);
  max-width: 340px;
  width: auto !important;
  padding: 0 !important;
  margin: 0 !important;
}

/* A rail holding one or two products still reads as a gap unless the cards
   themselves grow — "New products" and "Best Sellers" each hold exactly one.
   :has() is progressive: browsers without it just keep the base size above.

   Tablet and up ONLY. :has() outranks the plain selector in the phone block of
   §13, so leaving these unscoped silently dropped the mobile grid from two-up
   to one-up. */
@media (min-width: 768px) {
  #index .page-home .products.row:has(> .product-miniature:nth-child(3):last-child) > .product-miniature {
    flex-basis: clamp(260px, 24vw, 330px);
  }

  #index .page-home .products.row:has(> .product-miniature:nth-child(2):last-child) > .product-miniature {
    flex-basis: clamp(280px, 27vw, 370px);
    max-width: 380px;
  }

  #index .page-home .products.row:has(> .product-miniature:only-child) > .product-miniature {
    flex-basis: clamp(300px, 30vw, 400px);
    max-width: 420px;
  }
}

/* ============================================================================
   6. Product miniature card
   ----------------------------------------------------------------------------
   Moved out (2026-09-27). The card is defined once, site-wide, in
   card-premium.css — the homepage-only copy that lived here (#index-scoped,
   mostly !important) out-ranked it and made the homepage card a different
   object from the listing card. This file keeps only the homepage GRID (§5).

   Kept here: home-premium.js still tags empty review shells on this page.
   ========================================================================== */

#index .product-list-reviews.sk-is-empty {
  display: none !important;
}

/* ============================================================================
   7. Promo banner (ps_banner)
   ========================================================================== */

#index .page-home > a.banner {
  display: block;
  max-width: 1400px;
  margin: 0 auto !important;
  padding-inline: clamp(0px, 2vw, 28px);
  border-radius: 0 !important;
  overflow: visible !important;
}

#index .page-home > a.banner img {
  width: 100%;
  height: auto;
  object-fit: cover;
  border-radius: clamp(10px, 1.4vw, 18px);
  box-shadow: var(--sk-shadow-1);
  transition: transform var(--sk-dur-slow) var(--sk-ease),
              box-shadow var(--sk-dur-slow) var(--sk-ease);
}

@media (hover: hover) {
  #index .page-home > a.banner:hover img {
    transform: translateY(-4px) scale(1.012);
    box-shadow: var(--sk-shadow-2);
  }
}

#index .page-home > a.banner:focus-visible {
  outline: 3px solid var(--sk-pink);
  outline-offset: 6px;
  border-radius: clamp(10px, 1.4vw, 18px);
}

/* ---- Native promo block (.sk-promo — built by home-premium.js) -------------
   Desktop: visually hidden but still in the accessibility tree, so the banner
   link finally has an accessible name (the module emits alt="" title="").
   Phones: replaces the unreadable 86px-tall artwork entirely. */
#index .sk-promo {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

@media (max-width: 767.98px) {
  /* `> picture`: the artwork is wrapped in <picture> when its WebP twin is
     served (ps_banner.tpl, 2026-09-29). */
  #index a.banner.sk-has-promo > img,
  #index a.banner.sk-has-promo > picture {
    display: none;
  }

  #index a.banner.sk-has-promo {
    padding-inline: 0;
  }

  #index .sk-promo {
    position: static;
    width: auto;
    height: auto;
    margin: 0;
    padding: 1.5rem 1.35rem 1.6rem;
    overflow: visible;
    clip: auto;
    white-space: normal;
    text-align: left;
    background:
      radial-gradient(22rem 14rem at 100% 100%, rgba(255, 206, 84, .12), transparent 65%),
      linear-gradient(160deg, #fff 0%, var(--sk-pink-tint) 100%);
    border: 1px solid var(--sk-pink-line);
    border-radius: var(--sk-radius);
    box-shadow: var(--sk-shadow-1);
    position: relative;
  }

  /* Corner brackets, echoing the desktop artwork's framing. */
  #index .sk-promo::before,
  #index .sk-promo::after {
    content: '';
    position: absolute;
    width: 18px;
    height: 18px;
    border: 2px solid var(--sk-pink);
    opacity: .45;
    pointer-events: none;
  }

  #index .sk-promo::before {
    top: 10px;
    left: 10px;
    border-right: 0;
    border-bottom: 0;
    border-radius: 5px 0 0 0;
  }

  #index .sk-promo::after {
    right: 10px;
    bottom: 10px;
    border-left: 0;
    border-top: 0;
    border-radius: 0 0 5px 0;
  }

  #index .sk-promo__eyebrow {
    display: flex;
    align-items: center;
    gap: .5rem;
    font-size: .625rem;
    font-weight: 700;
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--sk-pink);
    margin-bottom: .7rem;
  }

  #index .sk-promo__eyebrow::before {
    content: '';
    width: 18px;
    height: 2px;
    background: var(--sk-pink);
    flex: 0 0 auto;
  }

  #index .sk-promo__title {
    font-family: 'Playfair Display', Georgia, serif;
    font-size: 1.4rem;
    font-weight: 600;
    line-height: 1.2;
    color: var(--sk-ink);
    margin: 0 0 .6rem;
  }

  #index .sk-promo__title em {
    font-style: italic;
    color: var(--sk-pink);
  }

  #index .sk-promo__copy {
    font-size: .8125rem;
    line-height: 1.6;
    color: var(--sk-ink-soft);
    margin: 0 0 1.15rem;
  }

  /* The one CTA button left on mobile. The hero's was removed by request; this
     one stays because the promo card is a separate offer rather than the page's
     opening statement. */
  #index .sk-promo__btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .55rem;
    min-height: 48px;
    min-width: min(100%, 15.5rem);
    padding: .75rem 1.5rem;
    border-radius: var(--sk-radius-pill);
    background: var(--sk-pink);
    color: #fff;
    font-size: .6875rem;
    font-weight: 700;
    letter-spacing: .13em;
    text-transform: uppercase;
    box-shadow:
      0 1px 2px rgba(26, 0, 16, .18),
      0 8px 18px rgba(213, 0, 117, .24),
      inset 0 1px 0 rgba(255, 255, 255, .17);
    transition: transform .14s ease, box-shadow .14s ease, background-color .14s ease;
  }

  #index .sk-promo__btn svg {
    width: 16px;
    height: 16px;
    stroke: currentColor;
    fill: none;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
  }

  #index a.banner.sk-has-promo:active .sk-promo__btn {
    transform: scale(.975);
    background-color: var(--sk-pink-dark);
  }

  #index a.banner.sk-has-promo:focus-visible {
    outline: none;
  }

  #index a.banner.sk-has-promo:focus-visible .sk-promo__btn {
    outline: 3px solid var(--sk-ink);
    outline-offset: 3px;
  }

  #index .sk-promo__note {
    display: block;
    margin-top: .9rem;
    font-size: .6875rem;
    color: var(--sk-ink-mute);
  }
}

/* ============================================================================
   8. Trust band (.sk-trust — markup lives in index.tpl)
   ========================================================================== */

#index .sk-trust {
  background:
    radial-gradient(60rem 30rem at 15% 0%, rgba(213, 0, 117, .045), transparent 60%),
    radial-gradient(50rem 26rem at 90% 100%, rgba(255, 206, 84, .09), transparent 60%),
    var(--sk-wash);
  border-block: 1px solid var(--sk-pink-line);
}

#index .sk-trust__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: clamp(1rem, 2vw, 1.75rem);
}

#index .sk-trust__item {
  display: flex;
  gap: 1rem;
  align-items: flex-start;
  padding: clamp(1.15rem, 2vw, 1.6rem);
  background: rgba(255, 255, 255, .72);
  border: 1px solid var(--sk-pink-line);
  border-radius: var(--sk-radius);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  transition: transform var(--sk-dur) var(--sk-ease),
              box-shadow var(--sk-dur) var(--sk-ease),
              border-color var(--sk-dur) var(--sk-ease);
}

@media (hover: hover) {
  #index .sk-trust__item:hover {
    transform: translateY(-6px);
    border-color: var(--sk-pink);
    box-shadow: var(--sk-shadow-2);
  }

  #index .sk-trust__item:hover .sk-trust__icon {
    background: var(--sk-pink);
    color: #fff;
    transform: rotate(-6deg) scale(1.06);
  }
}

#index .sk-trust__icon {
  flex: 0 0 auto;
  width: 46px;
  height: 46px;
  display: grid;
  place-items: center;
  border-radius: 14px;
  background: var(--sk-pink-tint);
  color: var(--sk-pink);
  transition: background var(--sk-dur) var(--sk-ease),
              color var(--sk-dur) var(--sk-ease),
              transform var(--sk-dur) var(--sk-ease);
}

#index .sk-trust__icon svg {
  width: 22px;
  height: 22px;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

#index .sk-trust__title {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: 1.0625rem;
  font-weight: 600;
  color: var(--sk-ink);
  margin: 0 0 .25rem;
  font-variant-numeric: lining-nums;
}

#index .sk-trust__copy {
  font-size: .8125rem;
  line-height: 1.55;
  color: var(--sk-ink-mute);
  margin: 0;
}

@media (min-width: 1200px) {
  #index .sk-trust__item { padding: 1.75rem 1.6rem; gap: 1.15rem; }
  #index .sk-trust__icon { width: 52px; height: 52px; border-radius: 16px; }
  #index .sk-trust__icon svg { width: 25px; height: 25px; }
  #index .sk-trust__title { font-size: 1.15rem; }
  #index .sk-trust__copy { font-size: .875rem; }
}

/* ============================================================================
   9. Closing CTA (.sk-cta — markup lives in index.tpl)
   ========================================================================== */

#index .sk-cta {
  background: var(--sk-paper);
}

#index .sk-cta__panel {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  border-radius: clamp(16px, 2vw, 26px);
  padding: clamp(2.25rem, 5vw, 4rem) clamp(1.5rem, 5vw, 4rem);
  text-align: center;
  color: #fff;
  background: linear-gradient(135deg, var(--sk-ink) 0%, #4a0230 55%, var(--sk-pink-dark) 100%);
  box-shadow: var(--sk-shadow-hero);
}

/* Oversized numeral watermark — same device the .semsons-section uses, so the
   page keeps one visual language top to bottom. */
#index .sk-cta__panel::before {
  content: '1978';
  position: absolute;
  right: -2%;
  top: 50%;
  transform: translateY(-50%);
  font-family: 'Playfair Display', Georgia, serif;
  font-size: clamp(9rem, 22vw, 20rem);
  font-weight: 700;
  line-height: .8;
  color: rgba(255, 255, 255, .045);
  pointer-events: none;
  z-index: -1;
  font-variant-numeric: lining-nums;
}

#index .sk-cta__panel::after {
  content: '';
  position: absolute;
  inset-inline: 0;
  top: 0;
  height: 3px;
  background: linear-gradient(90deg, var(--sk-pink), var(--sk-gold), var(--sk-pink));
}

#index .sk-cta__eyebrow {
  display: inline-block;
  font-size: .6875rem;
  font-weight: 700;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--sk-gold);
  margin-bottom: 1rem;
}

#index .sk-cta__title {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: clamp(1.75rem, 1.1rem + 2.4vw, 3rem);
  font-weight: 600;
  line-height: 1.12;
  letter-spacing: -.015em;
  color: #fff;
  margin: 0 0 .85rem;
}

#index .sk-cta__title em {
  font-style: italic;
  color: var(--sk-gold);
}

#index .sk-cta__copy {
  max-width: 46ch;
  margin: 0 auto clamp(1.75rem, 3vw, 2.25rem);
  font-size: clamp(.9375rem, .9rem + .2vw, 1.0625rem);
  line-height: 1.65;
  color: rgba(255, 255, 255, .82);
}

#index .sk-cta__actions {
  display: flex;
  flex-wrap: wrap;
  gap: .85rem;
  justify-content: center;
}

#index .sk-cta__btn {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  min-height: 50px;
  padding: .8rem 1.9rem;
  border-radius: var(--sk-radius-pill);
  font-size: .8125rem;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  text-decoration: none;
  border: 1.5px solid transparent;
  transition: transform var(--sk-dur) var(--sk-ease),
              box-shadow var(--sk-dur) var(--sk-ease),
              background var(--sk-dur) var(--sk-ease),
              color var(--sk-dur) var(--sk-ease);
}

#index .sk-cta__btn svg {
  width: 17px;
  height: 17px;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform var(--sk-dur) var(--sk-ease);
}

#index .sk-cta__btn--solid {
  background: #fff;
  color: var(--sk-pink-dark);
  box-shadow: 0 10px 30px rgba(0, 0, 0, .28);
}

#index .sk-cta__btn--ghost {
  background: transparent;
  color: #fff;
  border-color: rgba(255, 255, 255, .45);
}

@media (hover: hover) {
  #index .sk-cta__btn--solid:hover {
    transform: translateY(-3px);
    box-shadow: 0 18px 40px rgba(0, 0, 0, .38);
    color: var(--sk-pink-dark);
  }

  #index .sk-cta__btn--ghost:hover {
    background: rgba(255, 255, 255, .12);
    border-color: #fff;
    transform: translateY(-3px);
    color: #fff;
  }

  #index .sk-cta__btn:hover svg { transform: translateX(4px); }
}

#index .sk-cta__btn:focus-visible {
  outline: 3px solid var(--sk-gold);
  outline-offset: 3px;
}

#index .sk-cta__btn:active { transform: translateY(0) scale(.98); }

/* ============================================================================
   10. Scroll reveal
   ----------------------------------------------------------------------------
   The hidden start state is gated on `html.sk-js`, set by a one-line inline
   script in the <head>. If JS is disabled or home-premium.js fails to load,
   the class is never added and every element renders at its final state —
   content is never left invisible.
   ========================================================================== */

.sk-js #index .sk-reveal {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 620ms var(--sk-ease-out), transform 620ms var(--sk-ease-out);
  transition-delay: var(--sk-delay, 0ms);
  will-change: opacity, transform;
}

.sk-js #index .sk-reveal.sk-in {
  opacity: 1;
  transform: none;
  will-change: auto;
}

/* ============================================================================
   11. Touch / coarse-pointer behaviour
   ----------------------------------------------------------------------------
   Per THEME.md: :hover latches after a tap on touchscreens, so every transform
   above is inside `@media (hover: hover)`. Touch gets persistent controls and
   a short press response instead.
   ========================================================================== */

@media (hover: none), (pointer: coarse) {
  #index #home-slider .carousel-control-prev,
  #index #home-slider .carousel-control-next {
    opacity: .95 !important;
  }

  #index .sk-trust__item,
  #index .sk-cta__btn {
    transition: transform .12s ease, box-shadow .12s ease;
  }

  #index .sk-trust__item:active,
  #index .sk-cta__btn:active {
    transform: scale(.985);
  }

}

/* The touch quick-view / wishlist placement that lived here moved to
   card-premium.css §3 (2026-09-27). */

/* ============================================================================
   12. Reduced motion
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  #index *,
  #index *::before,
  #index *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }

  .sk-js #index .sk-reveal {
    opacity: 1 !important;
    transform: none !important;
  }

  #index #home-slider .carousel-item.active img {
    animation: none !important;
  }
}

/* ============================================================================
   13. Responsive
   ----------------------------------------------------------------------------
   Verified at 360 / 375 / 414 / 768 / 1024 / 1280 / 1440 / 1920.
   ========================================================================== */

/* ---- Tablet and below ---- */
@media (max-width: 991.98px) {
  #index .sk-head {
    align-items: flex-start;
  }
}

/* ---- Phones: the link wraps under the title -------------------------------
   Kept at its natural width and left-aligned with the title rather than
   stretched edge to edge — a full-width pill reads as the section's primary
   action, which "All products" is not. Still 44px tall. */
@media (max-width: 767.98px) {
  #index .sk-head {
    gap: .75rem 1rem;
  }

  #index .sk-head__link.all-product-link {
    order: 3;
    width: auto;
    align-self: flex-start;
  }
}

/* ---- Release theme.css's 240px carousel clamp -----------------------------
   Its "NUCLEAR FIX" block pins `.carousel` AND `.carousel-inner` to
   `max-height: 240px !important`, and forces `min-height: 280px` on
   `.carousel-item`, so the container was cropping the artwork's supporting line
   and stats row clean off — that is what made the mobile hero look cut short.
   The image's own aspect-ratio / max-height now govern the height and the
   container follows it.

   NOTE the breakpoint: theme.css writes `max-width: 768px` (inclusive) while
   this file uses `767.98px`. At exactly 768px CSS pixels the clamp applied but
   the release did not, and the hero clipped again — hence its own block. */
@media (max-width: 768px) {
  #index #home-slider .carousel.slide,
  #index #home-slider .carousel-inner,
  #index #home-slider .carousel-item {
    height: auto !important;
    max-height: none !important;
    min-height: 0 !important;
  }
}

/* ---- Phones ---- */
@media (max-width: 767.98px) {
  /* Two-up product grid: a single full-width card per row wastes the viewport
     and pushes the third product below two screenfuls of scroll. */
  #index .page-home .products.row {
    gap: 12px;
  }

  /* No grow (2026-09-27): with grow, the odd card of a three-product rail
     stretched to the 320px cap beside two ~177px cards and stood ~590px tall
     — one giant card under a tidy pair. Every card is now half the row; an
     odd last card is centred by the row's `justify-content: center`, and a
     one-product rail shows one normal-sized card. */
  #index .page-home .products.row > .product-miniature {
    flex: 0 1 calc(50% - 6px);
    min-width: 0;
    /* A rail holding ONE product used to grow to the full row: at 540px+ that
       produced a 516px-wide card with a 514px-tall square image, which is what
       made "New products" and "Best Sellers" look broken on a phone. The cap
       never bites on a two-up row (cards top out around 252px), so it only
       affects the lone-card case, which `justify-content: center` then centres. */
    max-width: 320px;
  }

  /* ---- Hero: crop to the message column ----------------------------------
     All three slides are 1920x720 artwork laid out as a text column on the
     left (headline, supporting line, CTA) and machine photography on the
     right. Fitting all 1920px into a 343px-wide phone renders the headline at
     roughly 11px — the hero's actual message is unreadable on the device most
     visitors arrive on.

     Cropping to the left ~47% and letting the artwork fill a 5:4 box puts the
     headline back at a legible size. Verified against all three slides: every
     text column ends before the 45% mark, so nothing informative is cut. If a
     future slide puts copy on the right, swap this for phone-specific slide
     images in the ps_imageslider back office instead. */
  #index #home-slider .carousel-item img {
    aspect-ratio: 5 / 4;
    width: 100% !important;
    height: auto !important;
    /* Without this cap the 5:4 box balloons with the viewport — a 767px-wide
       phone got a 613px-tall hero. When the cap bites, the box simply gets
       wider than 5:4 and `cover` reveals more of the artwork horizontally,
       which is the graceful direction: visible source width is
       boxAspect / 2.667, and every slide's text column ends by ~38%, so even
       the widest resulting box still frames all of it. */
    max-height: 420px !important;
    object-fit: cover !important;
    object-position: left center !important;
  }

  /* ---- Hero mode: equal-height slides, dots on the card -------------------
     home-premium.js adds `.sk-hero-mode` to #home-slider only when EVERY slide
     got a native block. That matters twice over: the dots may only sit on top of
     artwork we control, and the grid stacking below assumes every slide is a
     native block rather than a baked image.

     Two problems this solves:

     1. THE SLIDES WERE DIFFERENT HEIGHTS. `.carousel-inner` takes the height of
        whichever slide is active, so the frame grew and shrank on every
        transition — the "one is small and one is big" jump. Stacking every item
        in a single grid cell makes the frame as tall as the TALLEST slide and it
        never resizes again; the crossfade is then pure opacity.

     2. THE WHITE STRIP UNDER THE CARD. The dots previously sat in their own band
        below the image, which read as dead space. Now that what is underneath is
        our own gradient rather than baked artwork, they can sit on the card, and
        the hero reserves bottom padding so nothing collides. */

  #index #home-slider.sk-hero-mode .carousel.slide {
    display: block;
    background: var(--sk-pink-tint);
  }

  #index #home-slider.sk-hero-mode .carousel-inner {
    display: grid !important;
    grid-template-columns: 1fr !important;
    justify-items: stretch !important;
    max-height: none !important;
  }

  #index #home-slider.sk-hero-mode .carousel-item {
    grid-area: 1 / 1;
    position: relative !important;
    inset: auto !important;
    display: grid !important;
    width: 100%;
    /* theme.css's "Image Slider Fix" block puts `justify-content: center
       !important` and `align-items: center !important` on .carousel-item. Once
       this became a grid those stopped the auto column from stretching: each
       card sized to its OWN content and was then centred, so the three slides
       came out 408 / 369 / 373px wide with their buttons at different left
       edges. `1fr` pins the column to the container and stretch puts the card
       back on the same left margin for every slide. */
    grid-template-columns: 1fr !important;
    justify-items: stretch !important;
    align-items: stretch !important;
    justify-content: normal !important;
    align-content: normal !important;
    transform: none !important;
    transition: opacity 700ms cubic-bezier(.4, 0, .2, 1) !important;
  }

  #index #home-slider.sk-hero-mode .carousel-item:not(.active) {
    opacity: 0;
    pointer-events: none;
    z-index: 0;
  }

  #index #home-slider.sk-hero-mode .carousel-item.active {
    opacity: 1;
    z-index: 1;
  }

  /* Carry the grid cell's height down to the block itself.
     `.sk-has-hero` is in these selectors deliberately: section 2b sets
     `display: block !important` on the same elements at 2 ids + 3 classes, which
     outranks a 2-id + 2-class rule no matter how late it appears. Without the
     extra class the flex chain never formed and the card sat 80px short of the
     frame, leaving exactly the gap this is meant to close. */
  #index #home-slider.sk-hero-mode .carousel-item.sk-has-hero .carousel-link,
  #index #home-slider.sk-hero-mode .carousel-item.sk-has-hero .carousel-content {
    display: flex !important;
    flex-direction: column;
    height: 100%;
  }

  #index #home-slider.sk-hero-mode .carousel-item.sk-has-hero .carousel-content { flex: 1 1 auto; }
  #index #home-slider.sk-hero-mode .carousel-item.sk-has-hero .sk-hero { flex: 1 1 auto; }

  /* Where the slack goes — third attempt, and the one that holds.

     `space-between` (previous) spread the leftover height across the gaps, which
     meant the RHYTHM changed per slide: measured 39-42px between elements on
     slide 1 against 14-17px on slide 2. Same card, three different spacings —
     visibly uneven flicking through.

     Now the gap is fixed at 1.25rem everywhere and the leftover is absorbed by
     two things instead: slide 2's four short chips sit in a 2x2 grid rather than
     four stacked bars (about 87px shorter), which brings the three slides within
     ~40px of each other, and the photo band takes the small remainder with a
     270px cap so `cover` never crops it hard. */
  /* The photo band is FIXED and BOTTOM-ANCHORED, and this is the whole trick to
     the three slides looking like one card.

     Letting it grow to absorb leftover height meant it stopped growing once it
     hit its cap, and the remainder then sat underneath — so the band ended up at
     a different height on each slide (measured 30 / 24 / 0px of space below it
     at 440px wide). The photo visibly floated at three different positions.

     `margin-top: auto` pins it to the bottom instead and `flex: 0 0 auto` keeps
     its natural 5:3 box, so on every slide the photo is the SAME SIZE and its
     top and bottom edges land on the SAME LINE. All the leftover height collects
     in the single gap above it, between the text block and the photo — the one
     place where extra space reads as breathing room rather than a broken layout.
     It also means `cover` never crops: the band is always exactly 5:3. */
  #index #home-slider.sk-hero-mode .carousel-item.sk-has-hero .sk-hero__shot {
    flex: 0 0 auto;
    margin-top: auto;
  }

  /* Room for the dots. !important for the same reason as the base padding. */
  #index #home-slider.sk-hero-mode .carousel-item.sk-has-hero .sk-hero {
    padding-bottom: 3.15rem !important;
  }

  #index #home-slider.sk-hero-mode .carousel-indicators {
    position: absolute !important;
    inset-inline: 0;
    bottom: 15px !important;
    width: fit-content;
    margin: 0 auto !important;
    padding: 0 !important;
    background: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    box-shadow: none;
    border-radius: 0;
    z-index: 3;
  }

  /* ---- Entrance: the active slide's content settles in ---------------------
     Runs on load and on every change, so the crossfade reads as one composed
     movement rather than two stacked images swapping. Deliberately small. */
  #index #home-slider.sk-hero-mode .carousel-item.active .sk-hero > * {
    animation: sk-hero-in 620ms cubic-bezier(.16, 1, .3, 1) both;
  }

  #index #home-slider.sk-hero-mode .carousel-item.active .sk-hero > *:nth-child(1) { animation-delay:  40ms; }
  #index #home-slider.sk-hero-mode .carousel-item.active .sk-hero > *:nth-child(2) { animation-delay:  95ms; }
  #index #home-slider.sk-hero-mode .carousel-item.active .sk-hero > *:nth-child(3) { animation-delay: 150ms; }
  #index #home-slider.sk-hero-mode .carousel-item.active .sk-hero > *:nth-child(4) { animation-delay: 205ms; }
  #index #home-slider.sk-hero-mode .carousel-item.active .sk-hero > *:nth-child(5) { animation-delay: 255ms; }
  #index #home-slider.sk-hero-mode .carousel-item.active .sk-hero > *:nth-child(6) { animation-delay: 300ms; }

  @keyframes sk-hero-in {
    from { opacity: 0; transform: translateY(11px); }
    to   { opacity: 1; transform: none; }
  }

  /* ---- Indicators BELOW the frame — fallback only -------------------------
     Used when `.sk-hero-mode` is absent, i.e. a slide fell back to its baked
     artwork. Overlaid dots land about 64% down that artwork, right on top of its
     supporting line, so they go underneath instead. `.carousel-indicators` is
     the first child of `.carousel`, so `position: static` alone would put them
     ABOVE the image — the flex column plus `order` is what puts them under it. */
  #index #home-slider:not(.sk-hero-mode) .carousel.slide {
    display: flex;
    flex-direction: column;
    background: var(--sk-paper);
  }

  #index #home-slider:not(.sk-hero-mode) .carousel-inner { order: 1; }

  #index #home-slider:not(.sk-hero-mode) .carousel-indicators {
    order: 2;
    position: static !important;
    bottom: auto !important;
    width: auto;
    margin: 0 auto !important;
    /* 20px block padding gives the 4px bars their full 44px hit area without
       the carousel's `overflow: hidden` clipping the ::after extension. */
    padding: 20px 12px !important;
    background: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    box-shadow: none;
    border-radius: 0;
  }

  #index #home-slider .carousel-indicators button {
    background: rgba(26, 0, 16, .18) !important;
  }

  #index #home-slider .carousel-control-prev,
  #index #home-slider .carousel-control-next {
    width: 40px !important;
    height: 40px !important;
  }

  #index .sk-trust__item {
    padding: 1rem;
    gap: .85rem;
  }

  #index .sk-trust__icon {
    width: 40px;
    height: 40px;
    border-radius: 12px;
  }

  #index .sk-cta__actions {
    flex-direction: column;
  }

  #index .sk-cta__btn {
    width: 100%;
    justify-content: center;
  }
}

/* ---- Wide desktop: let the grid breathe rather than stretching cards ---- */
@media (min-width: 1400px) {
  #index .page-home .products.row > .product-miniature {
    flex-basis: 300px;
  }
}

/* ===========================================================================
   "All products" rail link — pre-script state + latched hover   (2026-08-28)

   Two defects, both measured in a real browser at 390px:

   1. THE BUTTON RESTYLED AND MOVED AFTER LOAD. Every rule for this control was
      scoped to `.sk-head__link`, a class home-premium.js adds when it relocates
      the link from the section footer into the header. That script is deferred,
      so the browser first painted a 144x38 transparent 4px-radius link at the
      BOTTOM of the rail, then jumped it to the top as a 178x44 white pill. The
      resting appearance is now declared on `.all-product-link` itself, so the
      control looks finished from first paint and the script only changes where
      it sits — not what it looks like.

   2. `:hover` LATCHED ON TOUCH. theme.css carries
        `.all-product-link:hover { background-color:#d50075 !important; color:#fff !important }`
      with no pointer guard, so after a tap on a phone the button stayed filled
      pink until something else took focus. project-docs/THEME.md records this
      exact failure mode for the homepage cards and the rule it implies — "guard
      every hover with @media (hover: hover)" — but this control predates it.
      Coarse pointers get the resting style back and a brief :active press.
   ======================================================================== */

/* Resting appearance, independent of where the script has put it. */
#index .all-product-link,
#index a.all-product-link {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  min-height: 44px;
  padding: 0.55rem 1.35rem;
  border-radius: 999px;
  background: #fff;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.2;
  text-decoration: none;
  transition: background-color var(--sk-dur, 320ms) var(--sk-ease, ease),
              color var(--sk-dur, 320ms) var(--sk-ease, ease),
              box-shadow var(--sk-dur, 320ms) var(--sk-ease, ease);
}

#index .all-product-link .material-icons {
  font-size: 18px !important;
}

/* Touch: no latched fill. Restore the resting look and press briefly instead. */
@media (hover: none), (pointer: coarse) {
  #index .all-product-link:hover,
  #index a.all-product-link:hover,
  #index .sk-head__link.all-product-link:hover {
    background: #fff !important;
    background-color: #fff !important;
    border-color: var(--sk-pink-line, #f0dce8) !important;
    color: #d50075 !important;
    box-shadow: none;
    transform: none;
  }

  #index .all-product-link:hover .material-icons,
  #index .sk-head__link.all-product-link:hover .material-icons {
    color: #d50075 !important;
    transform: none;
  }

  #index .all-product-link:active {
    background: #fef0f7 !important;
    background-color: #fef0f7 !important;
    transform: scale(0.985);
  }
}

@media (prefers-reduced-motion: reduce) {
  #index .all-product-link { transition: none; }
}
