/* ═══════════════════════════════════════════════════════════════════════════
   MAVEA — shared CASE STUDY template.

   ONE layout for every case-<brand>.html page. The pages differ only in their
   cover image, logo, copy and the inline window.CASE_STUDY config — everything
   structural lives here and in js/case-study.js.

   Page order:  cover → results bar → story → gallery → CTA
   The cover and the dark results bar are FULL-BLEED — edge to edge of the
   viewport, no gutter and no radius. Everything below them keeps the normal
   .cs-wrap container width.

   The whole case is deliberately COMPACT — it should read in about half a
   minute of scrolling, so every vertical clamp() here is kept tight.

   MOTION / NO-JS CONTRACT
   Nothing is hidden by default. The reveal states below are scoped under
   html.cs-anim, a class set by a tiny inline script in each page's <head>
   that runs ONLY when prefers-reduced-motion is not set. So:
     • reduced motion  → no .cs-anim → everything painted final, no count-up
     • JS / CDN broken → no .cs-anim → everything painted final
   Colours come from the site tokens in css/style.css (--cream --dark --grey
   --pink). Typography is Montserrat throughout: light body, ExtraBold accents.
   ═══════════════════════════════════════════════════════════════════════════ */

.cs-page { background: var(--cream); color: var(--dark); }

/* The page's H1. The design shows the brand as a logo image inside the cover,
   so the heading itself is visually hidden — but it still gives the document
   exactly one H1 naming the brand, for search engines and screen readers. */
.cs-sr-title {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Lenis smooth-scroll plumbing — same as every other page */
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-smooth [data-lenis-prevent] { overscroll-behavior: contain; }
.lenis.lenis-stopped { overflow: hidden; }

/* Shared measure: the cover, the bar, the story and the gallery all line up */
.cs-wrap {
  max-width: 1240px;
  margin: 0 auto;
  padding-inline: clamp(1.1rem, 5vw, 3rem);
}

/* ── Shared overline heading — the site's small-caps label + pink hairline ── */

.cs-overline {
  margin: 0 0 clamp(0.6rem, 1.4vw, 0.9rem);
  font-family: var(--font-display);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--grey);
}
.cs-overline::before {
  content: '';
  display: inline-block;
  width: 20px;
  height: 1px;
  margin-right: 0.65rem;
  vertical-align: middle;
  background: var(--pink);
}

/* ── Scroll reveal ─────────────────────────────────────────────────────────
   Only armed under html.cs-anim (see the motion contract above). --i is the
   stagger index, set inline on the markup where a group should cascade. */

.cs-anim [data-cs-reveal] {
  opacity: 0;
  transform: translateY(22px);
}
.cs-anim [data-cs-reveal].is-in {
  opacity: 1;
  transform: none;
  transition:
    opacity 700ms cubic-bezier(0.23, 1, 0.32, 1) calc(var(--i, 0) * 90ms),
    transform 700ms cubic-bezier(0.23, 1, 0.32, 1) calc(var(--i, 0) * 90ms);
}

/* ── COVER ───────────────────────────────────────────────────────────────
   FULL-BLEED: the cover and the dark results bar run edge to edge of the
   viewport, straight under the header — no side gutter, no radius, no
   floating-card look. Only their CONTENTS (the logo, the stats) sit on the
   shared .cs-wrap measure, so they line up with the story and gallery below. */

/* The site header is position:sticky, i.e. still IN FLOW — it already occupies
   its own height, so the cover butts straight against the header's bottom edge
   with nothing in between. */
.cs-head { padding-top: 0; }

.cs-cover {
  position: relative;
  margin: 0;
  width: 100%;
  height: clamp(210px, 40vh, 380px);
  border-radius: 0;
  overflow: hidden;
  background: var(--dark);
}
.cs-cover__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* Scrim: only as strong as the logo needs to stay legible on any frame. */
.cs-cover::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(15, 15, 15, 0.72) 0%, rgba(15, 15, 15, 0.2) 42%, rgba(15, 15, 15, 0) 68%);
  pointer-events: none;
}
/* full-width strip pinned to the bottom of the cover; the .cs-wrap inside it
   is what pulls the logo onto the content measure */
.cs-cover__foot {
  position: absolute;
  left: 0; right: 0;
  bottom: clamp(0.9rem, 2.2vw, 1.6rem);
  z-index: 2;
}
.cs-cover__logo {
  display: block;
  height: clamp(40px, 5.6vw, 72px);
  width: auto;
  max-width: 62%;
  object-fit: contain;
  object-position: left bottom;
  /* every brand mark → solid white, with a soft drop shadow so it still reads
     when the frame behind it is light */
  filter: brightness(0) invert(1) drop-shadow(0 2px 12px rgba(0, 0, 0, 0.5));
  opacity: 1;
}
/* Some brand marks are script wordmarks carrying a lot of internal air, so at
   the shared height they read much smaller than a compact logotype. This
   opt-in modifier scales one up WITHOUT touching the other case pages. */
.cs-cover__logo--lg {
  height: clamp(62px, 8.6vw, 112px);
  max-width: 74%;
}

/* ── RESULTS BAR — full-bleed, directly beneath the cover ──────────────── */

.cs-results {
  background: var(--dark);
  color: #fff;
  border-radius: 0;
  padding-block: clamp(1.05rem, 2.4vw, 1.6rem);
}
.cs-results__inner {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(0.9rem, 2.2vw, 1.6rem);
}
/* Every stat takes an equal share of the bar, so they spread across the full
   measure instead of bunching up on the left. */
.cs-stat { flex: 1 1 140px; min-width: 0; }
.cs-stat__value {
  display: inline-block;      /* shrink-wraps, so the draft rule below sits
                                 under the number and not across the column */
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(1.6rem, 3.2vw, 2.4rem);
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: var(--pink);
  /* the count-up rewrites this text — keep the digits from jittering */
  font-variant-numeric: tabular-nums;
}
.cs-stat__label {
  display: block;
  margin-top: 0.4rem;
  font-family: var(--font-display);
  font-size: 0.6rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  line-height: 1.5;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.5);
}
/* Placeholder numbers are marked ON PURPOSE — a dashed pink rule under every
   value, plus the note below the bar. Delete .cs-results--draft (and the note
   markup) once the real figures land and the marking disappears. */
.cs-results--draft .cs-stat__value {
  border-bottom: 2px dashed rgba(255, 81, 171, 0.5);
  padding-bottom: 0.18rem;
}
.cs-results__note {
  flex: 0 0 100%;
  margin: 0;
  font-family: var(--font-display);
  font-size: 0.58rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.3);
}

/* ── STORY — sticky chip rail on the left, blocks on the right ─────────── */

.cs-story { padding: clamp(2.2rem, 5vw, 3.6rem) 0 clamp(0.8rem, 2vw, 1.4rem); }

.cs-story__inner {
  display: grid;
  grid-template-columns: minmax(120px, 176px) minmax(0, 1fr);
  gap: clamp(1.6rem, 5vw, 4rem);
  align-items: start;
}

/* The rail rides along beside the story. --nav-h is published by js/main.js
   from the real header height, so the chips never tuck under the sticky bar. */
.cs-rail {
  position: sticky;
  top: calc(var(--nav-h, 80px) + 1.4rem);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.5rem;
}
.cs-chip {
  display: inline-block;
  padding: 0.42rem 0.85rem;
  border: 1px solid rgba(30, 30, 30, 0.22);
  border-radius: 100px;
  font-family: var(--font-display);
  font-size: 0.6rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--dark);
  white-space: nowrap;
}

.cs-blocks { min-width: 0; }
.cs-block + .cs-block { margin-top: clamp(1.6rem, 3.6vw, 2.6rem); }

.cs-block__text {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 300;
  font-size: clamp(0.95rem, 1.15vw, 1.05rem);
  line-height: 1.68;
  color: var(--dark);
  max-width: 62ch;
}
.cs-block__text + .cs-block__text { margin-top: 0.8rem; }
.cs-block__text strong { font-weight: 700; }

/* ── Marker highlight ──────────────────────────────────────────────────────
   A highlighter stroke swiped over a phrase. Built as a background-image so
   it sits BEHIND the glyphs with no stacking-context tricks and survives a
   line break (box-decoration-break). Default is fully drawn; only .cs-anim
   collapses it to 0 so it can wipe in on scroll. */

.cs-mark {
  background-image: linear-gradient(rgba(255, 81, 171, 0.32), rgba(255, 81, 171, 0.32));
  background-repeat: no-repeat;
  background-position: 0 84%;
  background-size: 100% 46%;
  padding: 0 0.08em;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
  font-weight: 400;
}
.cs-anim .cs-mark {
  background-size: 0% 46%;
  transition: background-size 800ms cubic-bezier(0.23, 1, 0.32, 1) 180ms;
}
.cs-anim .cs-mark.is-in { background-size: 100% 46%; }

/* ── Result check cards — 2 × 2 ────────────────────────────────────────── */

.cs-checks {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(0.6rem, 1.4vw, 0.9rem);
  margin-top: clamp(0.9rem, 2vw, 1.2rem);
  padding: 0;
  list-style: none;
}
/* An odd number of cards would leave a hole in the last row — let a lone
   trailing card span the full width instead. No effect on an even count. */
.cs-checks > .cs-check:last-child:nth-child(odd) { grid-column: 1 / -1; }

.cs-check {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  background: #fff;
  border-radius: 12px;
  padding: clamp(0.8rem, 1.7vw, 1.05rem);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.05);
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(0.82rem, 0.95vw, 0.9rem);
  line-height: 1.5;
  color: var(--dark);
  transition: transform 400ms cubic-bezier(0.23, 1, 0.32, 1), box-shadow 400ms ease;
}
.cs-check:hover { transform: translateY(-4px); box-shadow: 0 14px 32px rgba(0, 0, 0, 0.1); }
.cs-check__tick {
  flex: 0 0 auto;
  margin-top: 0.1rem;
  color: var(--pink);
}

/* ── GALLERY — ONE row of small tiles, same behaviour as the library page ── */

.cs-gallery { padding: clamp(1.4rem, 3.2vw, 2.2rem) 0 clamp(2.6rem, 6vw, 4.4rem); }

.cs-gallery__head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1.2rem;
  margin-bottom: clamp(0.8rem, 1.8vw, 1.1rem);
}
.cs-gallery__head .cs-overline { margin-bottom: 0; }
.cs-gallery__nav { display: none; gap: 8px; flex: 0 0 auto; }
@media (hover: hover) and (pointer: fine) { .cs-gallery__nav { display: flex; } }

.cs-strip-wrap { position: relative; }
.cs-strip {
  display: flex;
  gap: 10px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  padding: 4px 0 12px;
  scrollbar-width: none;
  -ms-overflow-style: none;
  cursor: grab;
}
.cs-strip::-webkit-scrollbar { display: none; }
.cs-strip.is-dragging { cursor: grabbing; scroll-snap-type: none; scroll-behavior: auto; }

/* Small tiles: six of them fit the 1240px measure in a single row, so the
   arrows and the edge fade switch themselves off (js sets .is-static). The
   min-width is what makes the row scroll instead of squashing on a phone. */
.cs-tile {
  position: relative;
  flex: 0 0 clamp(122px, 14.2vw, 172px);
  min-width: 122px;
  aspect-ratio: 9 / 16;
  border-radius: 12px;
  overflow: hidden;
  background: var(--dark);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
  scroll-snap-align: start;
  transition: transform 0.4s cubic-bezier(0.23, 1, 0.32, 1), box-shadow 0.4s ease;
}
.cs-tile:hover { transform: translateY(-5px); box-shadow: 0 18px 38px rgba(0, 0, 0, 0.15); }
.cs-tile video {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
  pointer-events: none;              /* the tile itself handles clicks */
}
/* ── View-count badge — organic-reach cases put the number on the tile ──
   White pill, bold figure, quiet label. Sits top-left so it never collides
   with the sound button in the bottom-right. */

.cs-tile__views {
  position: absolute;
  top: 7px; left: 7px;
  z-index: 2;
  display: inline-flex;
  align-items: baseline;
  gap: 0.28em;
  max-width: calc(100% - 14px);
  padding: 4px 8px;
  border-radius: 100px;
  background: rgba(255, 255, 255, 0.93);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  box-shadow: 0 3px 12px rgba(0, 0, 0, 0.18);
  font-family: var(--font-display);
  font-size: 0.5rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--grey);
  white-space: nowrap;
  pointer-events: none;               /* the tile underneath handles clicks */
}
.cs-tile__views b {
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: -0.01em;
  color: var(--dark);
}
/* Unconfirmed figure — marked the same way the draft stats are, so a
   placeholder can never be mistaken for a real number. */
.cs-tile__views--draft b {
  border-bottom: 2px dashed rgba(255, 81, 171, 0.6);
}

.cs-tile__sound {
  position: absolute;
  right: 7px; bottom: 7px;
  z-index: 2;
  width: 27px; height: 27px;
  display: flex; align-items: center; justify-content: center;
  border: 0;
  border-radius: 50%;
  background: rgba(20, 20, 20, 0.55);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  color: #fff;
  cursor: pointer;
  opacity: 0;
  transition: opacity 250ms ease, background 250ms ease;
}
.cs-tile:hover .cs-tile__sound,
.cs-tile.is-playing .cs-tile__sound { opacity: 1; }
.cs-tile__sound:hover { background: var(--pink); }
.cs-tile__sound .cs-ico--on { display: none; }
.cs-tile.has-sound .cs-tile__sound .cs-ico--on { display: block; }
.cs-tile.has-sound .cs-tile__sound .cs-ico--off { display: none; }
.cs-tile.has-sound .cs-tile__sound { background: var(--pink); opacity: 1; }

.cs-arrow {
  position: relative;
  width: 36px; height: 36px;
  border-radius: 50%;
  background: #fff;
  border: 1px solid rgba(0, 0, 0, 0.1);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.14);
  display: flex;
  align-items: center; justify-content: center;
  cursor: pointer;
  color: var(--dark);
  transition: transform 0.25s ease, box-shadow 0.25s ease, opacity 0.25s ease;
}
.cs-arrow:hover { transform: scale(1.07); box-shadow: 0 10px 26px rgba(0, 0, 0, 0.2); }
.cs-arrow[disabled] { opacity: 0.3; cursor: default; }
/* a row that already fits needs no controls and no "there is more" fade */
.cs-gallery.is-static .cs-gallery__nav,
.cs-strip-wrap.is-static::after { display: none; }
.cs-strip-wrap::after {
  content: '';
  position: absolute;
  top: 0; bottom: 12px; right: 0;
  width: clamp(28px, 5vw, 56px);
  background: linear-gradient(to right, rgba(252, 251, 250, 0), var(--cream));
  pointer-events: none;
}

/* ── Reduced motion ────────────────────────────────────────────────────────
   html.cs-anim is never set under reduced motion, so the reveals, the count-up
   and the marker wipe are already inert. This only kills the hover flourishes
   that live outside that contract. */
@media (prefers-reduced-motion: reduce) {
  .cs-tile, .cs-arrow, .cs-tile__sound, .cs-check { transition: none; }
  .cs-tile:hover, .cs-check:hover { transform: none; }
}

/* ── Narrow screens ────────────────────────────────────────────────────── */

@media (max-width: 860px) {
  /* the rail stops being a rail — chips become a wrapping row above the story */
  .cs-story__inner { grid-template-columns: minmax(0, 1fr); gap: clamp(1.2rem, 4vw, 1.8rem); }
  .cs-rail {
    position: static;
    flex-direction: row;
    flex-wrap: wrap;
    gap: 0.45rem;
  }
}

@media (max-width: 640px) {
  .cs-stat { flex: 1 1 40%; }                 /* two per row on a phone */
  .cs-checks { grid-template-columns: minmax(0, 1fr); }
}
