/* ==========================================================================
   Bunfire — stylesheet
   --------------------------------------------------------------------------
   Order of this file:
     1. Design tokens
     2. Reset and base elements
     3. Utilities
     4. Motion (scroll reveals)
     5. Components (button, swap, marquee, tag, claim, ...)
     6. Page sections, top to bottom
     7. Responsive
     8. Reduced motion

   Naming follows BEM: .block, .block__element, .block--variant.
   Change a colour or a font once in section 1 and it applies everywhere.
   ========================================================================== */

/* ==========================================================================
   1. Design tokens
   ========================================================================== */

:root {
  /* Brand colours. These six lines are the whole palette. */
  --color-primary: #1f4d3a; /* forest green: panels, headings */
  --color-primary-dark: #14382a; /* text on the lime accent */
  --color-accent: #d7f25a; /* lime: buttons, highlights */
  --color-surface: #f2f5ec; /* page background */
  --color-surface-light: #f7fbef; /* text on dark panels */
  --color-ink: #12211a; /* body text */

  /* Typography */
  --font-heading: "Poppins", system-ui, sans-serif;
  --font-body: "Inter", system-ui, sans-serif;
  --font-hand: "Just Another Hand", cursive; /* handwritten accents */

  /* Fluid type scale: min size, then growth, then max size. */
  --text-display: clamp(3rem, 2.2rem + 4.5vw, 7.5rem);
  --text-h2: clamp(2.25rem, 1.9rem + 1.8vw, 3.75rem);
  --text-h3: clamp(1.125rem, 1rem + 0.4vw, 1.5rem);
  --text-lead: clamp(1rem, 0.96rem + 0.2vw, 1.125rem);
  --text-body: 1rem;
  --text-small: 0.875rem;

  /* Spacing */
  --space-section: clamp(4rem, 2rem + 6vw, 8.75rem);
  --space-gutter: 1.25rem;
  --container-width: 1385px;

  /* Shapes */
  --radius-card: 20px;
  --radius-pill: 999px;

  /* Motion. One easing per intent, reused everywhere. */
  --duration: 250ms;
  --ease: cubic-bezier(0.2, 0.7, 0.3, 1);
  --ease-out-quad: cubic-bezier(0.25, 0.46, 0.45, 0.94);
  --ease-out-quart: cubic-bezier(0.165, 0.84, 0.44, 1);
  --ease-out-expo: cubic-bezier(0.19, 1, 0.22, 1);
  --ease-in-out-quad: cubic-bezier(0.455, 0.03, 0.515, 0.955);
  --ease-swing: cubic-bezier(0.175, 0.885, 0.32, 1.275); /* overshoots slightly */
}

/* ==========================================================================
   2. Reset and base elements
   ========================================================================== */

*,
*::before,
*::after {
  box-sizing: border-box;
}

* {
  margin: 0;
}

html {
  scroll-behavior: smooth;
  /* Sticky header height, so anchor links don't land under it. */
  scroll-padding-top: 6rem;
}

body {
  background-color: var(--color-surface);
  color: var(--color-ink);
  font-family: var(--font-body);
  font-size: var(--text-body);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden; /* the marquees are wider than the viewport */
}

h1,
h2,
h3 {
  font-family: var(--font-heading);
  font-weight: 700;
  line-height: 1.15;
  text-wrap: balance;
}

h2 {
  font-size: var(--text-h2);
}

h3 {
  font-size: var(--text-h3);
}

p {
  text-wrap: pretty;
}

img,
svg {
  display: block;
  max-width: 100%;
  height: auto;
}

ul {
  padding: 0;
  list-style: none;
}

a {
  color: inherit;
  text-decoration: none;
}

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  cursor: pointer;
}

/* One visible focus style for the whole site. */
:focus-visible {
  outline: 3px solid var(--color-accent);
  outline-offset: 3px;
  border-radius: 4px;
}

/* ==========================================================================
   3. Utilities
   ========================================================================== */

.container {
  width: 100%;
  max-width: var(--container-width);
  margin-inline: auto;
  padding-inline: var(--space-gutter);
}

/* Available to screen readers, invisible on screen. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.skip-link {
  position: absolute;
  top: 0;
  left: 50%;
  z-index: 100;
  padding: 0.75rem 1.25rem;
  background-color: var(--color-accent);
  color: var(--color-primary-dark);
  font-weight: 600;
  border-radius: 0 0 8px 8px;
  transform: translate(-50%, -110%);
  transition: transform var(--duration) var(--ease);
}

.skip-link:focus {
  transform: translate(-50%, 0);
}

/* ==========================================================================
   4. Motion — scroll reveals

   The hidden state is scoped to .js so that the page stays readable if
   the script fails to load: a stylesheet must never be able to hide
   content on its own. main.js adds .is-visible on the way in.

   Three flavours, matching the three the design uses:
     .reveal            slide up 40px          500ms
     .reveal--grow      grow from 75%         1000ms
     .reveal--unblur    grow from 0 + unblur   600ms
   And five stagger steps, .reveal--delay-1 to -5, 100ms apart.
   ========================================================================== */

.js .reveal:not(.reveal--unblur) {
  opacity: 0;
  transform: translateY(40px);
  transition: opacity 500ms var(--ease-out-quad) var(--reveal-delay, 0ms),
    transform 500ms var(--ease-out-quad) var(--reveal-delay, 0ms);
}

/* The :not() has to be repeated here: it is what makes the rule above
   specific enough to win, so this one needs the same weight to override it. */
.js .reveal--grow:not(.reveal--unblur) {
  transform: scale(0.75);
  transition-duration: 1000ms;
  transition-timing-function: var(--ease-out-quart);
}

.js .reveal.is-visible:not(.reveal--unblur) {
  opacity: 1;
  transform: none;
}

/* This one animates its child, not itself. An element scaled to 0 has no
   area at all, and IntersectionObserver would never report it as visible —
   it would stay hidden forever. Keeping the observed box intact avoids
   the trap, and it also frees the parent transform for the hero parallax. */
.js .reveal--unblur > * {
  transform: scale(0);
  filter: blur(5px);
  transition: transform 600ms ease var(--reveal-delay, 0ms),
    filter 600ms ease var(--reveal-delay, 0ms);
}

.js .reveal--unblur.is-visible > * {
  transform: none;
  filter: none;
}

.reveal--delay-1 { --reveal-delay: 100ms; }
.reveal--delay-2 { --reveal-delay: 200ms; }
.reveal--delay-3 { --reveal-delay: 300ms; }
.reveal--delay-4 { --reveal-delay: 400ms; }
.reveal--delay-5 { --reveal-delay: 500ms; }

/* ==========================================================================
   5. Components
   ========================================================================== */

/* --- Swap: two stacked copies of a label, sliding on hover -------------
   The box is one line tall and clips; both copies move up by one line,
   so the second takes the place of the first.
   ----------------------------------------------------------------------- */

.swap {
  --swap-duration: 400ms;
  --swap-ease: var(--ease-in-out-quad);
  display: block;
  height: 1.2em;
  overflow: clip;
  line-height: 1.2;
}

.swap > span {
  display: block;
  transition: transform var(--swap-duration) var(--swap-ease);
}

a:hover .swap > span,
a:focus-visible .swap > span {
  transform: translateY(-100%);
}

/* --- Button ------------------------------------------------------------
   At rest: lime pill. On hover a dark disc sweeps up from below and the
   label swaps to its light copy.
   ----------------------------------------------------------------------- */

.button {
  position: relative;
  isolation: isolate; /* keeps the sweep behind the label */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  overflow: clip;
  padding: 1.125rem 2.25rem;
  font-family: var(--font-heading);
  font-size: var(--text-small);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  border: 2px solid var(--color-accent);
  border-radius: var(--radius-pill);
}

.button--primary {
  background-color: var(--color-accent);
  color: var(--color-primary-dark);
}

.button--block {
  width: 100%;
}

.button .swap {
  --swap-duration: 650ms;
  --swap-ease: var(--ease-out-expo);
}

.button .swap > span:last-child {
  color: var(--color-surface-light);
}

.button::before {
  content: "";
  position: absolute;
  z-index: -1;
  top: 100%;
  left: -50%;
  width: 200%;
  aspect-ratio: 1;
  border-radius: 50%;
  background-color: var(--color-primary);
  transition: transform 650ms var(--ease-out-expo);
}

.button:hover::before,
.button:focus-visible::before {
  transform: translateY(-60%);
}

/* --- Brand -------------------------------------------------------------- */

.brand {
  font-family: var(--font-heading);
  font-size: clamp(1.5rem, 1.3rem + 0.6vw, 2rem);
  font-weight: 700;
  color: var(--color-surface-light);
}

/* --- Marquee ------------------------------------------------------------
   Identical copies of the text sit side by side. Sliding the track left by
   exactly one copy loops seamlessly, because what lands in view is the copy
   that was already there. Pure CSS, no JavaScript.

   --marquee-copies must match the number of .marquee__item in the markup,
   and the copies that stay behind must be wide enough to fill the screen:
   short text needs more copies. That is why the band below uses eight.
   --marquee-duration is the time for one copy to pass, so it also sets the
   speed: a wider copy with the same duration scrolls faster.
   ----------------------------------------------------------------------- */

.marquee {
  --marquee-copies: 3;
  --marquee-duration: 20s;
  overflow: hidden;
  user-select: none;
}

.marquee__track {
  display: flex;
  width: max-content;
  animation: marquee-scroll var(--marquee-duration) linear infinite;
}

.marquee--reverse .marquee__track {
  animation-direction: reverse;
}

.marquee__item {
  padding-inline: 0.4em;
  font-family: var(--font-heading);
  font-weight: 700;
  text-transform: uppercase;
  white-space: nowrap;
}

@keyframes marquee-scroll {
  to {
    transform: translateX(calc(-100% / var(--marquee-copies)));
  }
}

/* Oversized lines used in the hero and above the footer. Their copies are
   very wide, hence the longer duration for the same reading speed. */
.marquee--hero {
  --marquee-duration: 22.5s;
}

.marquee--hero .marquee__item {
  font-size: var(--text-display);
  line-height: 1;
  color: var(--color-primary);
}

/* Outlined text: transparent fill plus a stroke. */
.marquee--outline .marquee__item {
  color: transparent;
  -webkit-text-stroke: 1.5px var(--color-primary);
}

/* Compact band on a coloured strip. Short text, so more copies — and a
   shorter duration, because one copy is only a few hundred pixels wide. */
.marquee--band {
  --marquee-copies: 8;
  --marquee-duration: 5s;
  padding-block: 0.85rem;
  background-color: var(--color-surface);
}

.marquee--band .marquee__item {
  display: flex;
  gap: 1.5rem;
  align-items: center;
  font-size: clamp(1.25rem, 1.1rem + 0.7vw, 1.875rem);
  color: var(--color-primary);
}

.marquee--band .marquee__item i {
  font-style: normal;
}

/* The footer variant repeats a long sentence, so three copies are plenty.
   The colour has to be restated: .marquee--band sets a solid colour further
   up and would otherwise win over the outline rule (same specificity, later
   in the file). */
.marquee--band.marquee--outline {
  --marquee-copies: 3;
  --marquee-duration: 20s;
}

.marquee--band.marquee--outline .marquee__item {
  font-size: clamp(2.5rem, 1.8rem + 3.5vw, 5.5rem);
  color: transparent;
}

/* --- Tag: handwritten pill dropping over the statement photo ------------
   Each tag falls from above with its own tilt and its own delay. Resting
   position, start angle and delay are set per tag in section 6.
   ----------------------------------------------------------------------- */

.tag {
  position: absolute;
  padding: 1rem 1.5rem;
  color: #fff;
  white-space: nowrap;
  border: 1px solid rgba(255, 255, 255, 0.9);
  border-radius: var(--radius-pill);
  transform: rotate(var(--tag-angle, 0deg)) translateY(var(--tag-shift, 0));
}

.tag span {
  display: block;
  font-family: var(--font-hand);
  font-size: 1.5rem;
  line-height: 1;
}

/* They wait far above the section, then fall in one after the other. The
   trigger is on the section, not on the tags: a tag parked a thousand
   pixels off screen never "enters" the viewport on its own. */
.js .tag {
  transform: translateY(-1000px) rotate(var(--tag-angle-from, 0deg));
  transition: transform 500ms var(--ease-swing) var(--tag-delay, 0ms);
}

.js [data-reveal-group].is-visible .tag {
  transform: rotate(var(--tag-angle, 0deg)) translateY(var(--tag-shift, 0));
}

/* --- Claim: handwritten line with a dashed arrow ------------------------- */

.claim {
  font-family: var(--font-hand);
  font-size: clamp(1.5rem, 1.2rem + 1vw, 2.25rem);
  line-height: 1.15;
  color: var(--color-primary);
}

.claim__arrow {
  width: clamp(120px, 14vw, 200px);
  margin-bottom: 0.35rem;
}

/* ==========================================================================
   6. Page sections
   ========================================================================== */

/* --- Announcement bar --------------------------------------------------- */

.announcement {
  padding: 0.9rem var(--space-gutter);
  background-color: var(--color-accent);
  color: var(--color-primary-dark);
  font-size: var(--text-small);
  font-weight: 500;
  text-align: center;
}

/* --- Header ------------------------------------------------------------- */

.header {
  position: sticky;
  top: 0;
  z-index: 50;
  background-color: var(--color-primary);
}

.header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  min-height: 5.75rem;
}

.nav {
  display: flex;
  align-items: center;
  gap: clamp(1.5rem, 3vw, 4rem);
}

.nav__list {
  display: flex;
  gap: clamp(1rem, 2vw, 2rem);
}

.nav__link {
  display: block;
  color: var(--color-surface-light);
  font-weight: 500;
}

.nav__link .swap > span:last-child {
  color: var(--color-accent);
}

/* Hamburger. Hidden on desktop, see the responsive section. */
.nav-toggle {
  display: none;
  flex-direction: column;
  gap: 6px;
  padding: 0.75rem 0.25rem;
}

.nav-toggle__bar {
  display: block;
  width: 26px;
  height: 2px;
  background-color: var(--color-surface-light);
  transition: transform var(--duration) var(--ease), opacity var(--duration) var(--ease);
}

/* Turn the two bars into a cross while the menu is open. Target them by
   position, not with :last-child — the button's last child is the
   screen-reader label, not a bar. */
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(1) {
  transform: translateY(4px) rotate(45deg);
}

.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(2) {
  transform: translateY(-4px) rotate(-45deg);
}

/* --- Hero --------------------------------------------------------------- */

.hero {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3.5rem;
  min-height: min(88vh, 896px);
  padding-block: 120px 140px;
  overflow: hidden;
}

/* The two lines cross behind the product shot. */
.hero .marquee--hero {
  position: absolute;
  right: 0;
  left: 0;
}

.hero .marquee--hero:first-of-type {
  top: 45%;
}

.hero .marquee--hero:nth-of-type(2) {
  top: 60%;
}

/* The wrapper carries the pointer parallax, the image the reveal:
   two elements, so the two transforms never overwrite each other. */
.hero__product {
  position: relative;
  z-index: 1;
  width: min(520px, 78vw);
  transform: translate(calc(var(--pointer-x, 0) * 50px), calc(var(--pointer-y, 0) * 50px));
  transition: transform 900ms cubic-bezier(0.2, 0.8, 0.2, 1);
}

.hero__cta {
  position: relative;
  z-index: 2;
  --reveal-delay: 300ms; /* the shot lands first, then the button */
}

/* --- About -------------------------------------------------------------- */

.about {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: stretch;
}

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

.about__panel {
  display: flex;
  align-items: center;
  padding: clamp(2.5rem, 5vw, 6rem) clamp(1.25rem, 4vw, 4.5rem);
  background-color: var(--color-primary);
  color: var(--color-surface-light);
}

.about__content {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1.75rem;
  max-width: 40rem;
}

/* --- Generic section ---------------------------------------------------- */

.section {
  padding-block: var(--space-section);
}

.section__head {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.5rem;
  max-width: 44rem;
  margin-inline: auto;
  margin-bottom: clamp(2.5rem, 5vw, 4.5rem);
  text-align: center;
}

.section__head h2 {
  color: var(--color-primary);
}

.lead {
  font-size: var(--text-lead);
}

/* --- Product cards ------------------------------------------------------ */

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
  gap: clamp(1rem, 2vw, 1.5rem);
}

.product {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background-color: var(--color-primary);
  /* The dish sits on a panel the same colour as the page, so the outline
     is what makes the card read as a card. */
  border: 1px solid var(--color-primary);
  border-radius: var(--radius-card);
}

/* The cream panel sits behind the dish and slides out of the way on
   hover, so the card colour shows through. */
.product__media {
  position: relative;
  overflow: clip;
  aspect-ratio: 1;
  padding: 3.75rem 1rem 1rem; /* room around the dish, more at the top */
}

.product__media-bg {
  position: absolute;
  inset: 0;
  background-color: var(--color-surface);
  transition: transform 600ms ease;
}

.product__image {
  position: relative;
  width: 100%;
  height: 100%;
  object-fit: contain;
  transition: transform 400ms ease;
}

.product:hover .product__media-bg {
  transform: translateY(-101%);
}

.product:hover .product__image {
  transform: rotate(10deg);
}

.product__body {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: clamp(1.25rem, 2vw, 1.75rem);
  color: var(--color-surface-light);
}

.product__name {
  text-transform: uppercase;
}

.product__price {
  padding-bottom: clamp(1.25rem, 2vw, 1.75rem);
  border-bottom: 1px dashed rgba(247, 251, 239, 0.35);
}

.product__body .button {
  margin-top: clamp(1.25rem, 2vw, 1.75rem);
}

/* --- Category circles --------------------------------------------------- */

.category-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr));
  gap: clamp(1.5rem, 3vw, 2.5rem);
}

.category {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.5rem;
}

.category__disc {
  position: relative;
  isolation: isolate;
  display: grid;
  place-items: center;
  overflow: clip;
  aspect-ratio: 1;
  width: 100%;
  padding: 12%;
  border: 1px solid rgba(31, 77, 58, 0.45);
  border-radius: 50%;
}

/* Sweeps up from below on hover, behind the dish. */
.category__fill {
  position: absolute;
  z-index: -1;
  inset: 0;
  background-color: var(--color-primary);
  border-radius: 50%;
  transform: translateY(100%);
  transition: transform 400ms ease;
}

.category__disc:hover .category__fill,
.category__disc:focus-visible .category__fill {
  transform: none;
}

.category__name {
  color: var(--color-primary);
  text-transform: uppercase;
}

/* --- Signature ---------------------------------------------------------- */

/* Claims in the outer columns, product shot spanning the middle one. */
.signature__stage {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  grid-template-rows: auto auto;
  align-items: center;
  gap: clamp(1.5rem, 4vw, 4rem) clamp(1rem, 2vw, 2rem);
}

.signature__image {
  grid-column: 2;
  grid-row: 1 / span 2;
  width: min(620px, 100%);
}

.claim--top-left {
  grid-area: 1 / 1;
  justify-self: end;
  text-align: right;
}

.claim--bottom-left {
  grid-area: 2 / 1;
  justify-self: end;
  text-align: right;
}

.claim--top-right {
  grid-area: 1 / 3;
}

.claim--bottom-right {
  grid-area: 2 / 3;
}

.claim--top-left .claim__arrow,
.claim--bottom-left .claim__arrow {
  margin-left: auto;
}

/* --- Statement ----------------------------------------------------------
   The inner box is the headline itself: the tags are placed against its
   edges, and the section padding leaves room for the ones that overhang.
   ------------------------------------------------------------------------ */

.statement {
  position: relative;
  padding-block: clamp(5rem, 20vw, 294px);
  background-color: var(--color-ink);
  background-image: url("../img/statement-background.avif");
  background-position: center;
  background-size: cover;
  isolation: isolate;
  overflow: clip; /* hides the tags until they drop in */
}

/* Dark veil so the white headline keeps enough contrast over the photo. */
.statement::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-color: rgba(18, 33, 26, 0.55);
}

.statement__inner {
  position: relative;
  max-width: 61.25rem;
  margin-inline: auto;
}

.statement__title {
  font-size: clamp(1.875rem, 1.4rem + 2.6vw, 3.75rem);
  color: #fff;
  text-align: center;
  text-transform: uppercase;
}

.statement__title em {
  font-style: normal;
  color: var(--color-accent);
}

/* Two tags above the headline, five below. Each one: where it rests, the
   angle it starts at, the angle it lands on, and when it falls. */
.tag--1 { top: -52px; left: -2%; --tag-angle-from: 0deg; --tag-angle: -10deg; --tag-delay: 0ms; }
.tag--2 { top: -52px; right: 6%; --tag-angle-from: 45deg; --tag-angle: 0deg; --tag-delay: 200ms; }
.tag--3 { bottom: -110px; left: 41.6%; --tag-angle-from: 10deg; --tag-angle: 0deg; --tag-delay: 500ms; }
.tag--4 { bottom: -110px; left: 59.3%; --tag-angle-from: -90deg; --tag-angle: 0deg; --tag-delay: 800ms; }
.tag--5 { bottom: -49px; right: 30%; --tag-angle-from: 45deg; --tag-angle: 0deg; --tag-delay: 1000ms; }
.tag--6 { bottom: -85px; left: 0; --tag-angle-from: 90deg; --tag-angle: 0deg; --tag-delay: 1200ms; }
.tag--7 { bottom: -52px; left: 25%; --tag-angle-from: 0deg; --tag-angle: -16deg; --tag-shift: 14px; --tag-delay: 1300ms; }

/* --- Reviews carousel ---------------------------------------------------
   Native scroll snapping does the work: drag, swipe, trackpad and keyboard
   all come for free. main.js only marks the centred card and wires the
   arrows. The viewport is not clipped, so the neighbours stay visible.
   ------------------------------------------------------------------------ */

.reviews {
  /* Space left beside a centred card — used to pad both ends of the track. */
  --reviews-edge: max(var(--space-gutter), calc(50vw - 355px));
  display: flex;
  flex-direction: column;
  gap: 2.5rem;
}

.reviews__viewport {
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
}

.reviews__viewport::-webkit-scrollbar {
  display: none;
}

.reviews__track {
  display: flex;
  gap: 1.5rem;
  /* Padding on the start side only: a scrolling flex container does not
     count its end padding in the scrollable width, which would leave the
     last card impossible to bring to the middle. The spacer below does
     that job instead — it is a flex item, so it always counts. */
  padding-inline-start: var(--reviews-edge);
  padding-block: 2rem;
}

.reviews__track::after {
  content: "";
  flex: 0 0 var(--reviews-edge);
}

.review {
  display: flex;
  flex: 0 0 min(710px, 82vw);
  flex-direction: column;
  gap: 1.5rem;
  padding: clamp(1.5rem, 2.5vw, 2.5rem);
  scroll-snap-align: center;
  border: 1px solid rgba(31, 77, 58, 0.3);
  border-radius: var(--radius-card);
  /* Resting state of a neighbour: smaller and tilted. */
  transform: scale(0.9) rotate(-5deg);
  transition: transform 400ms var(--ease), background-color 400ms ease, color 400ms ease,
    border-color 400ms ease;
}

.review.is-active {
  background-color: var(--color-primary);
  color: var(--color-surface-light);
  border-color: transparent;
  transform: none;
}

.review__stars {
  color: var(--color-primary);
  font-size: 1.25rem;
  letter-spacing: 0.2em;
  transition: color 400ms ease;
}

.review.is-active .review__stars {
  color: var(--color-surface-light);
}

.review blockquote {
  flex: 1;
  font-size: var(--text-lead);
}

.review__author {
  display: flex;
  gap: 1rem;
  align-items: center;
}

.review__author img {
  width: 3rem;
  height: 3rem;
  object-fit: cover;
  border-radius: 50%;
}

.review__author figcaption {
  font-family: var(--font-heading);
  font-size: var(--text-h3);
  font-weight: 700;
}

.reviews__controls {
  display: flex;
  gap: 1rem;
  justify-content: center;
}

.reviews__arrow {
  display: grid;
  place-items: center;
  width: 50px;
  height: 50px;
  color: var(--color-primary);
  border: 2px solid var(--color-primary);
  border-radius: 50%;
  transition: background-color var(--duration) var(--ease), color var(--duration) var(--ease);
}

.reviews__arrow svg {
  width: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.reviews__arrow:hover {
  background-color: var(--color-primary);
  color: var(--color-surface-light);
}

/* --- FAQ ---------------------------------------------------------------- */

.faq__layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr);
  gap: clamp(2rem, 5vw, 5rem);
  align-items: start;
}

.faq__title {
  color: var(--color-primary);
  text-transform: uppercase;
}

.faq__list {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

.faq__item {
  padding: 1.5rem;
  border: 1px solid rgba(31, 77, 58, 0.3);
  border-radius: 14px;
  transition: background-color 400ms ease, border-color 400ms ease;
}

.faq__item:hover {
  border-color: var(--color-primary);
}

/* The open question turns lime. */
.faq__item[open] {
  background-color: var(--color-accent);
  border-color: var(--color-accent);
}

.faq__item summary {
  display: flex;
  gap: 1rem;
  align-items: center;
  justify-content: space-between;
  font-family: var(--font-heading);
  font-size: var(--text-h3);
  font-weight: 600;
  color: var(--color-primary);
  cursor: pointer;
  list-style: none; /* hide the native triangle */
}

.faq__item summary::-webkit-details-marker {
  display: none;
}

/* A "+" drawn from two bars; the vertical one rotates away on open. */
.faq__item summary::after {
  content: "";
  flex: none;
  width: 18px;
  height: 18px;
  background-image: linear-gradient(var(--color-primary) 0 0),
    linear-gradient(var(--color-primary) 0 0);
  background-position: center;
  background-repeat: no-repeat;
  background-size: 100% 2px, 2px 100%;
  transition: background-size 400ms ease;
}

.faq__item[open] summary::after {
  background-size: 100% 2px, 2px 0;
}

.faq__panel {
  overflow: hidden;
}

.faq__panel p {
  padding-top: 1rem;
  color: var(--color-primary);
}

/* --- Call to action -----------------------------------------------------
   The five photos start off-centre and slide into place as the section
   crosses the screen. main.js writes the 0 → 1 progress into --progress;
   everything below is derived from it, so there is no animation code here
   and no animation values in the script.
   ------------------------------------------------------------------------ */

.cta {
  /* 1 = at rest. main.js overwrites this on load, so a page without
     JavaScript simply shows the finished layout. */
  --progress: 1;
  padding-block: var(--space-section);
  /* The photos start outside the section; without this they would widen
     the page and add a horizontal scrollbar on the way in. */
  overflow-x: clip;
}

.cta__inner {
  position: relative;
}

.cta__content {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.75rem;
  max-width: 42rem;
  margin-inline: auto;
  text-align: center;
  /* Fades in between 15% and 30% of the run. */
  --in: clamp(0, calc((var(--progress) - 0.15) / 0.15), 1);
  opacity: var(--in);
  transform: scale(calc(0.95 + 0.05 * var(--in)));
}

.cta__content h2 {
  color: var(--color-primary);
  text-transform: uppercase;
}

.cta__figure {
  overflow: hidden;
  aspect-ratio: 3 / 3.6;
  border-radius: 12px;
  /* 1 at the start of the run, 0 once the photo has landed (35%). */
  --travel: clamp(0, calc((0.35 - var(--progress)) / 0.35), 1);
  transform: translate(calc(var(--from-x, 0%) * var(--travel)), calc(var(--from-y, 0%) * var(--travel)));
}

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

/* Where each photo comes from, as a share of its own size. */
.cta__figure--1 { --from-x: 90%; --from-y: 70%; }
.cta__figure--2 { --from-x: 90%; --from-y: -50%; }
.cta__figure--3 { --from-x: 10%; --from-y: -130%; }
.cta__figure--4 { --from-x: -80%; --from-y: 60%; }
.cta__figure--5 { --from-x: -60%; --from-y: -60%; }

/* Wide screens: the copy sits in the middle column of a grid and the photos
   take the outer cells. A grid rather than absolute positioning, so nothing
   can ever land on top of the text — whatever the length of the headline. */
@media (min-width: 1024px) {
  .cta__inner {
    display: grid;
    /* Fixed-width photo columns keep the section from growing too tall. */
    grid-template-columns: minmax(0, 15rem) minmax(0, 1fr) minmax(0, 15rem);
    gap: clamp(1.5rem, 3vw, 3rem);
    align-items: start;
  }

  /* The list itself is not a box here: its items join the parent grid. */
  .cta__gallery {
    display: contents;
  }

  .cta__content {
    grid-column: 2;
    grid-row: 1 / span 2;
    align-self: center;
  }

  .cta__figure--1 { grid-area: 1 / 1; }
  .cta__figure--2 { grid-area: 1 / 3; }
  .cta__figure--3 { grid-area: 2 / 1; }
  .cta__figure--5 { grid-area: 2 / 3; }

  /* Under the copy, narrower and centered. */
  .cta__figure--4 {
    grid-area: 3 / 2;
    width: min(320px, 100%);
    margin-inline: auto;
  }
}

/* Narrower screens: a simple strip under the copy. */
@media (max-width: 1023px) {
  .cta__gallery {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
    gap: 0.75rem;
    margin-top: 3rem;
  }
}

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

.footer {
  background-color: var(--color-primary);
  color: var(--color-surface-light);
}

.footer .marquee--band {
  background-color: var(--color-surface);
}

/* Full width, natural proportions: no crop, so the burger keeps its bun. */
.footer__image {
  width: 100%;
  height: auto;
}

.footer__inner {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 1.4fr) auto;
  gap: clamp(2rem, 4vw, 4rem);
  padding-block: clamp(2.5rem, 5vw, 4rem);
}

.footer__brand {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  max-width: 22rem;
}

.footer__nav {
  display: flex;
  gap: clamp(2rem, 6vw, 6rem);
}

.footer__nav ul {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.footer__link .swap > span:last-child {
  color: var(--color-accent);
}

.footer__actions {
  display: flex;
  gap: 1rem;
  align-items: center;
}

.socials {
  display: flex;
  gap: 0.75rem;
}

.socials a {
  display: grid;
  place-items: center;
  width: 3.25rem;
  height: 3.25rem;
  color: var(--color-accent);
  border: 1px solid var(--color-accent);
  border-radius: 50%;
  transition: background-color var(--duration) var(--ease), color var(--duration) var(--ease);
}

.socials svg {
  width: 1.25rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
}

.socials a:hover {
  background-color: var(--color-accent);
  color: var(--color-primary);
}

.footer__bottom {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 2rem;
  justify-content: space-between;
  padding-block: 1.75rem;
  font-size: var(--text-small);
  border-top: 1px solid rgba(247, 251, 239, 0.2);
}

/* ==========================================================================
   7. Responsive
   ========================================================================== */

/* Tablet and below: stack the two-column blocks. */
@media (max-width: 900px) {
  .about {
    grid-template-columns: 1fr;
  }

  .about__image {
    aspect-ratio: 4 / 3;
  }

  .faq__layout {
    grid-template-columns: 1fr;
  }

  /* Claims move under the product shot; the arrows only read side by side. */
  .signature__stage {
    grid-template-columns: 1fr 1fr;
  }

  .signature__image {
    grid-column: 1 / -1;
    grid-row: 1;
    justify-self: center;
  }

  .claim {
    grid-area: auto !important;
    justify-self: start !important;
    text-align: left !important;
  }

  .claim__arrow {
    display: none;
  }

  .footer__inner {
    grid-template-columns: 1fr;
  }
}

/* Mobile: the nav collapses into a panel toggled by the hamburger. */
@media (max-width: 768px) {
  .nav-toggle {
    display: flex;
    order: 2;
  }

  .nav {
    position: absolute;
    top: 100%;
    right: 0;
    left: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 1.5rem;
    padding: 1.5rem var(--space-gutter) 2rem;
    background-color: var(--color-primary);
    border-top: 1px solid rgba(247, 251, 239, 0.15);
    /* Hidden by default, revealed by the .is-open class from main.js. */
    display: none;
  }

  .nav.is-open {
    display: flex;
  }

  .nav__list {
    flex-direction: column;
    gap: 1.25rem;
  }

  .header__inner {
    position: relative;
    min-height: 4.5rem;
  }

  .hero {
    padding-block: 4rem 5rem;
  }

  .hero .marquee--hero:first-of-type {
    top: 42%;
  }

  .hero .marquee--hero:nth-of-type(2) {
    top: 56%;
  }

  .tag {
    display: none; /* not enough room to scatter them legibly */
  }
}

/* ==========================================================================
   8. Reduced motion
   Respect the visitor's system setting: no scrolling text, no reveals,
   no parallax, no sweeps.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }

  .js .reveal,
  .js .tag {
    opacity: 1;
    transform: none;
    filter: none;
  }

  .hero__product {
    transform: none;
  }

  .marquee__track {
    animation: none;
  }
}
