/* ==========================================================================
   hero.css — the animated product hero, used on both storefronts
   --------------------------------------------------------------------------
   Modelled on the Apocalypse Coffee hero: a two-column split with the message
   on the left and a fan of product cards on the right, small product discs
   drifting around behind everything, and a diagonal wipe on load.

   THE THREE TYPEFACES
     Permanent Marker   the first headline line — the brush stroke
     Archivo Black      the second headline line — the heavy punchline
     Space Mono         everything else: pills, eyebrow, body, buttons

     They come from Google Fonts, which is the one thing on this site that
     needs the internet. Every rule below names a real fallback, so opened
     from a USB stick with no connection the hero still reads correctly — it
     just loses the brush and the typewriter character.

   BRAND COLOUR
     Nothing here hard-codes red or blue. It all runs off --brand and
     --brand-2 from store.css, so the pneumatics hero comes out red and the
     hero can be restyled from that one token.
   ========================================================================== */

/* ------------------------------- tokens -------------------------------- */
:root {
  --vh-bg: #f1f0ea;          /* warm paper, the colour the reference sits on */
  --vh-ink: #262626;
  --vh-ink-soft: #4f4f4f;
  --vh-hard: #1d1d1d;        /* the hard offset shadow, no blur anywhere */
  --vh-brush: "Permanent Marker", "Comic Sans MS", cursive;
  --vh-heavy: "Archivo Black", "Arial Black", "Segoe UI Black", sans-serif;
  --vh-mono: "Space Mono", ui-monospace, "Cascadia Mono", Consolas, monospace;

  /*
    THE READING FACE. Every paragraph a customer actually has to read uses this.
    It used to be --vh-mono, and Space Mono is a lovely typewriter face but a
    poor one for prose: fixed-width letterforms, a small x-height and no real
    bold. Three-line paragraphs got away with it; the three-reason section's
    are eight lines each and they were hard work.
    Space Mono stays on the small tracked-out labels, which is the job it is
    good at.
  */
  --vh-text: "Inter", "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
}

/* ================================ shell ================================ */
.vhero {
  position: relative;
  isolation: isolate;
  overflow: hidden;                 /* clips the wipe and the cropped card */
  background: var(--vh-bg);
  border-bottom: 1px solid rgba(0, 0, 0, 0.09);
}

.vhero__inner {
  position: relative;
  z-index: 2;
  display: grid;
  gap: clamp(2rem, 4vw, 3rem);
  align-items: center;
  padding-block: clamp(2.25rem, 5vw, 4rem) clamp(2.5rem, 5vw, 4rem);
}

@media (min-width: 900px) {
  .vhero__inner {
    grid-template-columns: minmax(0, 1.02fr) minmax(0, 0.98fr);
    min-height: 39rem;
  }
}

/* ----------------------------- diagonal wipe ---------------------------
   A soft band of brand colour sweeps across once as the page arrives. It is
   the transition the reference site plays between pages; here it just marks
   the hero appearing. Purely decorative, so it never takes pointer events.
   --------------------------------------------------------------------- */
.vhero__wipe {
  position: absolute;
  inset: -20% -60%;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(
    100deg,
    transparent 42%,
    color-mix(in srgb, var(--brand) 32%, transparent) 47%,
    color-mix(in srgb, var(--brand) 32%, transparent) 53%,
    transparent 58%
  );
  transform: translateX(-120%);
  animation: vwipe 1500ms cubic-bezier(0.5, 0, 0.2, 1) 120ms both;
}

@keyframes vwipe {
  from { transform: translateX(-120%); }
  to   { transform: translateX(120%); }
}

/* =============================== the copy ============================== */
.vhero__copy { position: relative; z-index: 3; }

/* Everything in the left column arrives in sequence rather than all at once.
   --i is the position in that queue, set on each element in the markup. */
.vhero__copy > * {
  animation: vrise 620ms cubic-bezier(0.2, 0.9, 0.25, 1) both;
  animation-delay: calc(220ms + var(--i, 0) * 110ms);
}

@keyframes vrise {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}

/* -------------------------------- pills -------------------------------- */
.vhero__pills {
  display: flex;
  flex-wrap: wrap;
  gap: 0.55rem;
  margin-bottom: 1.6rem;
}

.vpill {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.62rem 1rem;
  border: 1.5px solid var(--vh-hard);
  border-radius: 999px;
  background: transparent;
  font-family: var(--vh-mono);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--vh-ink);
  white-space: nowrap;
}

.vpill__dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #1f9d4d;              /* the "in stock" green from the reference */
}

/* ------------------------------- headline ------------------------------ */
.vhero__eyebrow {
  font-family: var(--vh-mono);
  font-size: clamp(0.78rem, 1.1vw, 0.92rem);
  font-weight: 700;
  letter-spacing: 0.17em;
  text-transform: uppercase;
  color: var(--vh-ink);
  margin-bottom: 0.7rem;
}

.vhero__title { margin: 0 0 1.35rem; }

.vhero__title span { display: block; }

/* line one: the brush stroke, in brand colour */
.vt-brush {
  font-family: var(--vh-brush);
  font-weight: 400;
  font-size: clamp(2.5rem, 7.2vw, 4.6rem);
  line-height: 0.96;
  letter-spacing: 0.005em;
  color: var(--brand);
  /* Permanent Marker sits high in its box; pull it back down so the two
     lines look optically stacked rather than gapped. */
  margin-bottom: -0.06em;
}

/* line two: the heavy punchline */
.vt-heavy {
  font-family: var(--vh-heavy);
  font-weight: 900;
  font-size: clamp(2.35rem, 6.6vw, 4.35rem);
  line-height: 1.0;
  letter-spacing: -0.022em;
  text-transform: uppercase;
  color: var(--vh-ink);
}

/* --------------------------------- body -------------------------------- */
.vhero__body {
  max-width: 34rem;
  margin-bottom: 1.9rem;
  font-family: var(--vh-text);
  font-size: clamp(1rem, 1.15vw, 1.09rem);
  line-height: 1.72;
  color: var(--vh-ink-soft);
}

/* ------------------------------- buttons ------------------------------- */
.vhero__cta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem 1.6rem;
}

/*
  The hard offset shadow is the signature of this style: a solid block of
  colour behind the button, no blur at all. Pressing it slides the button
  onto its own shadow, which is what makes it feel physical.
*/
.vbtn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.95rem 1.6rem;
  border: 1.5px solid var(--vh-hard);
  border-radius: 999px;
  background: var(--brand);
  color: #fff;
  font-family: var(--vh-mono);
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  cursor: pointer;
  box-shadow: 4px 4px 0 0 var(--vh-hard);
  transition: transform 140ms ease, box-shadow 140ms ease, background 200ms ease;
}

.vbtn:hover {
  background: var(--brand-2);
  transform: translate(2px, 2px);
  box-shadow: 2px 2px 0 0 var(--vh-hard);
}

.vbtn:active {
  transform: translate(4px, 4px);
  box-shadow: 0 0 0 0 var(--vh-hard);
}

/* the secondary action is a plain underlined link, as in the reference */
.vbtn-link {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding-bottom: 0.2rem;
  border-bottom: 2px solid var(--vh-hard);
  font-family: var(--vh-mono);
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--vh-ink);
  transition: color 200ms ease, border-color 200ms ease, gap 200ms ease;
}

.vbtn-link:hover { color: var(--brand-2); border-color: var(--brand); gap: 0.85rem; }

/* ============================== the stage ==============================
   Three product cards in a fan. The middle one stands taller and sits in
   front; the outer two are pushed down and back, and the right one runs off
   the edge of the section on purpose.
   ===================================================================== */
.vhero__stage {
  position: relative;
  z-index: 3;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  min-height: 26rem;
}

.vpack {
  position: relative;
  display: block;
  width: clamp(9rem, 15.5vw, 13.5rem);
  aspect-ratio: 3 / 4;
  border: 1.5px solid var(--vh-hard);
  border-radius: 14px;
  background: #fff;
  overflow: hidden;
  box-shadow: 5px 5px 0 0 var(--vh-hard);
  animation: vpack-in 760ms cubic-bezier(0.2, 0.9, 0.25, 1) both;
  transition: transform 260ms cubic-bezier(0.2, 0.9, 0.25, 1),
              box-shadow 260ms ease;
}

.vpack img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

@keyframes vpack-in {
  from { opacity: 0; transform: translateY(30px) scale(0.96); }
  to   { opacity: 1; }
}

/* the fan: outer cards tucked behind and lower, and slightly rotated */
.vpack--l {
  z-index: 1;
  margin-right: -3.2rem;
  transform: translateY(2.1rem) rotate(-4deg);
  animation-delay: 420ms;
}

.vpack--c {
  z-index: 3;
  width: clamp(10.5rem, 18vw, 15.5rem);
  animation-delay: 300ms;
}

.vpack--r {
  z-index: 2;
  margin-left: -3.2rem;
  transform: translateY(2.1rem) rotate(4deg);
  animation-delay: 540ms;
}

/*
  Hover lifts the card and swaps the black shadow for a brand-coloured one.
  The rotation has to be repeated in each hover rule — a transform replaces
  the whole value, so leaving it out would snap the outer cards upright.
*/
.vpack--l:hover { transform: translateY(1.1rem) rotate(-4deg); }
.vpack--c:hover { transform: translateY(-1rem); }
.vpack--r:hover { transform: translateY(1.1rem) rotate(4deg); }

.vpack:hover { box-shadow: 7px 7px 0 0 var(--brand); z-index: 5; }

/* ------------------------------- tooltip ------------------------------- */
/*
  Follows the pointer while a card is hovered, the way the reference names
  each coffee. Positioned by assets/js/hero.js.
*/
.vtip {
  position: absolute;
  z-index: 8;
  left: 0;
  top: 0;
  max-width: 15rem;
  padding: 0.7rem 0.95rem;
  border: 1.5px solid var(--vh-hard);
  border-radius: 12px;
  background: #fff;
  box-shadow: 4px 4px 0 0 var(--vh-hard);
  pointer-events: none;
  opacity: 0;
  transform: translate(-50%, -118%) scale(0.96);
  transition: opacity 160ms ease, transform 200ms cubic-bezier(0.2, 0.9, 0.25, 1);
}

.vtip.is-on { opacity: 1; transform: translate(-50%, -118%) scale(1); }

.vtip__meta {
  font-family: var(--vh-mono);
  font-size: 0.63rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--brand-2);
}

.vtip__name {
  font-family: var(--vh-heavy);
  font-size: 0.92rem;
  line-height: 1.2;
  text-transform: uppercase;
  color: var(--vh-ink);
  margin-top: 0.2rem;
}

.vtip__spec {
  font-family: var(--vh-mono);
  font-size: 0.7rem;
  line-height: 1.45;
  color: var(--vh-ink-soft);
  margin-top: 0.25rem;
}

/* --------------------------- under-stage button ------------------------ */
.vhero__under {
  position: relative;
  z-index: 4;
  display: flex;
  justify-content: center;
  margin-top: 1.4rem;
  animation: vrise 620ms cubic-bezier(0.2, 0.9, 0.25, 1) 760ms both;
}

.vbundle {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.85rem 1.35rem;
  border: 1.5px solid var(--vh-hard);
  border-radius: 999px;
  background: #fff;
  font-family: var(--vh-mono);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--vh-ink);
  box-shadow: 3px 3px 0 0 var(--vh-hard);
  transition: transform 140ms ease, box-shadow 140ms ease, background 200ms ease;
}

.vbundle:hover {
  background: var(--brand);
  color: #fff;
  transform: translate(1.5px, 1.5px);
  box-shadow: 1.5px 1.5px 0 0 var(--vh-hard);
}

/* ----------------------------- corner note ---------------------------- */
.vhero__note {
  position: absolute;
  z-index: 4;
  right: clamp(1rem, 4vw, 2.5rem);
  bottom: clamp(0.75rem, 2vw, 1.25rem);
  padding-bottom: 0.25rem;
  border-bottom: 2.5px solid var(--brand);
  font-family: var(--vh-mono);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--vh-ink);
  animation: vrise 620ms ease 1000ms both;
}

@media (max-width: 640px) { .vhero__note { display: none; } }

/* ========================== floating discs ============================
   Small circular crops of real stock, drifting behind the content. Each one
   carries its own position, colour, drift length and delay as custom
   properties in the markup, so this is one rule rather than eight.
   ==================================================================== */
.vhero__float {
  position: absolute;
  inset: 0;
  /* Above the copy/fan so the discs are genuinely clickable. The layer itself
     stays click-through (pointer-events:none); only the discs below opt back
     in, so the empty space still passes clicks to the buttons underneath. The
     discs are positioned clear of the headline and the CTA buttons. */
  z-index: 6;
  pointer-events: none;
  overflow: hidden;
}

.vdot {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: var(--s, 58px);
  height: var(--s, 58px);
  border-radius: 50%;
  background: var(--c, #f5c542);
  /* the discs are clickable links to products */
  pointer-events: auto;
  cursor: pointer;
  will-change: transform;
  /* a gentle, continuous drift: a smooth sine ease and a path that returns to
     its start, so the loop never jerks at the turnaround */
  animation: vdrift var(--t, 22s) cubic-bezier(0.37, 0, 0.63, 1) var(--d, 0s) infinite;
  transition: filter 220ms ease;
}
.vdot:hover,
.vdot:focus-visible { animation-play-state: paused; filter: drop-shadow(0 8px 16px rgba(0, 0, 0, 0.28)); }
.vdot:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }

/* the photo sits slightly off the disc, so a rim of colour shows through */
.vdot img {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
  border: 1.5px solid var(--vh-hard);
  transform: translate(-4px, -4px);
  transition: transform 240ms cubic-bezier(0.2, 0.9, 0.25, 1);
}
.vdot:hover img,
.vdot:focus-visible img { transform: translate(-4px, -4px) scale(1.14); }

@keyframes vdrift {
  0%   { transform: translate(0, 0) rotate(0deg); }
  25%  { transform: translate(11px, -15px) rotate(4deg); }
  50%  { transform: translate(-7px, -25px) rotate(-3deg); }
  75%  { transform: translate(-15px, -11px) rotate(3deg); }
  100% { transform: translate(0, 0) rotate(0deg); }
}

/* Behind the text the discs would fight the words, so on narrow screens —
   where the columns stack and the text fills the width — only the ones in
   the far corners stay. */
@media (max-width: 899px) {
  .vdot { --s: 46px; }
  .vdot[data-keep="no"] { display: none; }
}

/* ============================== responsive ============================= */
@media (max-width: 899px) {
  .vhero__stage { min-height: 0; margin-top: 0.5rem; }
  .vpack--l, .vpack--r { margin-inline: -2.2rem; }
}

@media (max-width: 520px) {
  .vhero__cta { gap: 0.85rem 1rem; }
  .vbtn, .vbtn-link { font-size: 0.7rem; }
  .vpack { border-radius: 11px; box-shadow: 4px 4px 0 0 var(--vh-hard); }
}

/* ============================ reduced motion ==========================
   Someone who has asked their system for less movement should not get eight
   things drifting and a band sweeping across. Everything lands in its final
   position immediately instead.
   ==================================================================== */
@media (prefers-reduced-motion: reduce) {
  .vhero__wipe { display: none; }
  .vdot { animation: none; }
  .vhero__copy > *,
  .vpack,
  .vhero__under,
  .vhero__note { animation: none; opacity: 1; transform: none; }

  /* the fan still needs its offsets, which the reset above just wiped */
  .vpack--l { transform: translateY(2.1rem) rotate(-4deg); }
  .vpack--r { transform: translateY(2.1rem) rotate(4deg); }
}
