/* ============================================================
   TM3 United — v2 editorial layer
   Loaded after tm3.css. Shared primitives for the tm3v2_* sections:
   poster type, pill buttons, full-bleed helpers, 16px media cards.

   Design intent: full-bleed 0-radius sections, big imagery, minimal
   copy. Radius lives on the cards and media panels, not the shell.
   Colors come from the existing theme tokens — no new palette.
   ============================================================ */

:root {
  --v2-radius: 16px;
  --v2-radius-lg: 24px;
  --v2-max: 1440px;
  --v2-gutter: clamp(20px, 4.2vw, 64px);
  /* Outer inset that matches .v2-wrap's content edge (centering + gutter). Used by
     full-bleed split panels (opportunity, promo split) so their text starts at the
     same left/right edge as every contained section, instead of hugging closer. */
  --v2-align: max(var(--v2-gutter), calc((100vw - var(--v2-max)) / 2 + var(--v2-gutter)));
  --v2-media-fill: var(--clr-gray, #E8EDEB);
}

/* ---- layout helpers ---- */
.v2-wrap { max-width: var(--v2-max); margin: 0 auto; padding-inline: var(--v2-gutter); }
.v2-wrap--flush { padding-inline: 0; }
.v2-bleed { width: 100%; }

/* Section head: eyebrow + display heading + optional link, one row on desktop */
.v2-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 24px; flex-wrap: wrap; margin-bottom: clamp(20px, 2.6vw, 34px); }
.v2-head__text { display: flex; flex-direction: column; gap: 8px; min-width: 0; }

/* ---- poster type ----
   Hanken Grotesk at 700, uppercase, tight leading. Stands in for the
   condensed display face the reference uses. */
.v2-display {
  font-family: var(--ff-heading), sans-serif;
  font-weight: 700;
  text-transform: uppercase;
  line-height: 0.92;
  letter-spacing: -0.005em;
  margin: 0;
}
.v2-display > * { font: inherit; letter-spacing: inherit; text-transform: inherit; line-height: inherit; margin: 0; color: inherit; }
.v2-display--xl { font-size: clamp(40px, 7.4vw, 104px); }
.v2-display--lg { font-size: clamp(32px, 4.6vw, 64px); }
.v2-display--md { font-size: clamp(26px, 4.2vw, 42px); }
.v2-display--sm { font-size: clamp(20px, 2.1vw, 28px); letter-spacing: 0.02em; }

/* Mono label — the small-caps kicker used above headings and on cards */
.v2-eyebrow {
  font-family: var(--ff-accent), monospace;
  font-size: var(--text-xs);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--clr-muted);
  margin: 0;
}
.v2-eyebrow > * { font: inherit; letter-spacing: inherit; color: inherit; margin: 0; }
.v2-eyebrow--onDark { color: rgba(243, 245, 243, 0.66); }

.v2-lede { font-family: var(--ff-body), sans-serif; font-size: var(--text-base); line-height: 1.5; color: var(--clr-muted); margin: 0; max-width: 48ch; }
.v2-lede > * { font: inherit; color: inherit; margin: 0; }
.v2-lede--onDark { color: rgba(243, 245, 243, 0.72); }

/* ---- pill buttons ----
   Four independent axes, all driven by custom properties the markup sets
   inline: Style (filled/outline/text), Color, Hover behaviour, Hover Color.
   Hover states can't be inline styles, so the variables carry the values and
   these static rules do the work.

     --btn-c    base colour        --btn-fg   readable ink on --btn-c
     --btn-hc   hover colour       --btn-hfg  readable ink on --btn-hc
*/
.v2-btn {
  --btn-c: var(--clr-primary);
  --btn-fg: var(--clr-white);
  --btn-hc: var(--btn-c);
  --btn-hfg: var(--btn-fg);
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  font-family: var(--ff-body), sans-serif;
  font-size: var(--text-xs); font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase;
  line-height: 1; text-decoration: none; white-space: nowrap; cursor: pointer;
  padding: 15px 32px; min-height: 44px; box-sizing: border-box; border-radius: 1000px; border: 1.5px solid transparent;
  transition: background-color .2s, color .2s, border-color .2s, transform .2s, box-shadow .2s, filter .2s;
}
.v2-btn:active { transform: translateY(1px); }

/* Style */
.v2-btn--filled  { background: var(--btn-c); color: var(--btn-fg); border-color: var(--btn-c); }
.v2-btn--outline { background: transparent; color: var(--btn-c); border-color: var(--btn-c); }
.v2-btn--text    { background: transparent; color: var(--btn-c); border-color: transparent; padding-inline: 4px; }

/* Hover */
.v2-btn--hover-darken:hover  { filter: brightness(0.86); }
.v2-btn--hover-lighten:hover { filter: brightness(1.14); }
.v2-btn--hover-lift:hover    { transform: translateY(-2px); box-shadow: 0 10px 22px rgba(13, 58, 64, .22); }
.v2-btn--hover-underline:hover { color: var(--btn-hc); text-decoration: underline; text-underline-offset: 6px; text-decoration-thickness: 1.5px; }
.v2-btn--hover-fill:hover    { background: var(--btn-hc); color: var(--btn-hfg); border-color: var(--btn-hc); }
/* Filled + Fill swaps one solid for another; outline/text fill in from transparent */
.v2-btn--hover-none:hover    { /* deliberately inert */ }

/* Gradient-flow hover — on hover a teal gradient with lime + purple pops drifts
   diagonally from the top-left, anchored on #00BBC5. Available as the
   `v2-btn--hover-flow` button style (the "Gradient flow" Hover option), and
   applied by default to the commerce CTAs (add-to-cart + cart checkout).

   Panning a diagonal gradient via background-position tiles it and leaves a hard
   seam. Instead an oversized ::before layer holds the (repeating) gradient and is
   TRANSLATED by exactly one period (400px along the 135deg axis ≈ 283px per axis).
   Because it's one rigid layer, oversized and clipped by the button, there is no
   tile edge — the loop is truly seamless and every colour passes through. */
@keyframes v2-cta-flow { to { transform: translate(283px, 283px); } }
.v2-btn--hover-flow,
button[data-fluid-add-to-cart],
.checkout-btn { position: relative; overflow: hidden; z-index: 0; }
.v2-btn--hover-flow:hover,
button[data-fluid-add-to-cart]:hover,
.checkout-btn:hover { filter: none; }
/* The gradient layer is always present but transparent, so it can fade in/out
   gently on hover rather than snapping on. The drift animation runs continuously
   underneath; only its opacity is toggled. */
.v2-btn--hover-flow::before,
button[data-fluid-add-to-cart]::before,
.checkout-btn::before {
  content: ""; position: absolute; inset: -340px; z-index: -1;
  pointer-events: none; opacity: 0;
  transition: opacity .45s ease;
  background: repeating-linear-gradient(135deg,
    #00bbc5 0px, #8fd15f 128px, #00bbc5 200px, #9a44b0 272px, #00bbc5 400px);
  animation: v2-cta-flow 9s linear infinite;
}
.v2-btn--hover-flow:hover::before,
button[data-fluid-add-to-cart]:hover::before,
.checkout-btn:hover::before { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .v2-btn--hover-flow::before,
  button[data-fluid-add-to-cart]::before,
  .checkout-btn::before { animation: none; }
  .v2-btn--hover-flow:hover::before,
  button[data-fluid-add-to-cart]:hover::before,
  .checkout-btn:hover::before { transition: none; }
}

/* Unavailable add-to-cart (out of stock or not sold in the shopper's country).
   Set by the availability guard in tm3v2.js; the click is also blocked there. */
.v2-btn.v2-unavailable,
button[data-fluid-add-to-cart].v2-unavailable {
  background: var(--clr-gray, #E8EDEB) !important;
  color: var(--clr-muted, #6b7a78) !important;
  cursor: not-allowed; pointer-events: none; box-shadow: none; filter: none;
}
.v2-unavailable::before { content: none !important; display: none !important; }

/* Text link with arrow — used in section heads */
.v2-link {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--ff-body), sans-serif;
  font-size: var(--text-xs); font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase;
  color: inherit; text-decoration: none;
  padding-bottom: 3px; border-bottom: 1.5px solid currentColor;
  transition: opacity .2s;
  /* tap-target floor: grow the hit area, not the visual, on touch widths */
}
.v2-link:hover { opacity: .6; }

/* ---- cart toast (FairShare renders it in the light DOM) ---- */
.v2-toast {
  border-radius: 10px;
  font-family: var(--ff-body), sans-serif;
  font-size: var(--text-sm);
  letter-spacing: .01em;
}
.v2-toast[data-variant="success"] { background: var(--clr-secondary); color: var(--clr-light); }
.v2-toast[data-variant="error"]   { background: #9b2c2c; color: #fff; }

/* ---- media ---- */
.v2-media { position: relative; overflow: hidden; background: var(--v2-media-fill); border-radius: var(--v2-radius); }
.v2-media--flat { border-radius: 0; }
.v2-media > img, .v2-media > video { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Labelled placeholder shown until a real image is picked */
.v2-ph { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; padding: 16px; text-align: center;
  background: linear-gradient(150deg, #eef1ef 0%, #e2eae8 52%, #cfe0de 100%); }
.v2-ph span {
  font-family: var(--ff-accent), monospace; font-size: var(--text-xs); letter-spacing: .14em; text-transform: uppercase;
  color: var(--clr-muted); border: 1px dashed var(--clr-line, rgba(13,58,64,.16)); border-radius: 1000px;
  padding: 7px 15px; background: rgba(255,255,255,.45);
}

/* Ribbon badge on product/offer cards. Colour comes from the palette via
   --bdg-c, with --bdg-fg carrying the readable ink the section works out. */
.v2-badge {
  --bdg-c: var(--clr-accent);
  --bdg-fg: var(--clr-secondary);
  display: inline-block; font-family: var(--ff-body), sans-serif;
  font-size: var(--text-xs); font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
  padding: 6px 12px; border-radius: 3px; line-height: 1;
  background: var(--bdg-c); color: var(--bdg-fg);
}

/* ---- horizontal scroll rail (product + tile carousels) ---- */
.v2-rail {
  display: grid; grid-auto-flow: column; grid-auto-columns: var(--v2-rail-item, 268px);
  gap: var(--v2-rail-gap, 18px);
  overflow-x: auto;
  /* Horizontal only. Leaving overflow-y at its default makes the browser
     compute it to auto (because overflow-x isn't visible), and the reveal
     animation's translateY plus the card hover lift then make the rail
     scrollable vertically inside the section. */
  overflow-y: hidden;
  /* proximity, not mandatory — mandatory fights programmatic scrolling and
     yanks the rail back to its start */
  scroll-snap-type: x proximity;
  scrollbar-width: none; -ms-overflow-style: none;
  /* Breathing room so overflow-y: hidden doesn't crop the hover lift/shadow. */
  padding-block: 6px 30px;
  margin-bottom: -24px;
}
.v2-rail::-webkit-scrollbar { display: none; }
.v2-rail > * { scroll-snap-align: start; }
/* No scroll-behavior here on purpose. Native smooth scrolling (CSS or the
   scrollBy option) is dropped outright by some engines, which leaves the arrow
   buttons dead. tm3v2.js tweens scrollLeft itself and honours reduced motion. */

.v2-navbtns { display: inline-flex; gap: 8px; }
.v2-navbtns[hidden] { display: none; }
.v2-navbtn {
  width: 40px; height: 40px; border-radius: 50%; display: grid; place-items: center;
  background: transparent;
  /* currentColor keeps the ring visible on both light and dark sections */
  border: 1.5px solid currentColor;
  color: inherit; opacity: .38; cursor: pointer;
  transition: opacity .2s, background-color .2s;
}
.v2-navbtn:hover:not([disabled]) { opacity: 1; }
.v2-navbtn[disabled] { opacity: .14; cursor: default; }
.v2-navbtn svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2; }

/* ---- marquee ---- */
.v2-marquee { display: flex; overflow: hidden; user-select: none; }
.v2-marquee__track { display: flex; flex: none; gap: 0; width: max-content; animation: v2-scroll var(--v2-marquee-speed, 34s) linear infinite; }
.v2-marquee:hover .v2-marquee__track { animation-play-state: paused; }
@keyframes v2-scroll { from { transform: translateX(0); } to { transform: translateX(-100%); } }
@media (prefers-reduced-motion: reduce) {
  .v2-marquee { overflow-x: auto; }
  .v2-marquee__track { animation: none; }
}

/* ---- shared responsive ---- */
@media (max-width: 767px) {
  .v2-head { align-items: flex-start; }
  .v2-btn { padding: 14px 26px; }
}

/* ─────────────────────────────────────────────────────────────────
   Tap-target floor (audited 2026-08-17). Measured at 375px: standalone
   text controls were 19–24px tall against a 44px minimum. These rules
   grow the HIT AREA only — the negative margin cancels the added padding
   so nothing moves visually.
   ───────────────────────────────────────────────────────────────── */
@media (hover: none) and (pointer: coarse) {
  .v2-link {
    padding-top: 10px;
    padding-bottom: 13px;
    margin-top: -10px;
    margin-bottom: -10px;
  }
}

