/* ═══════════════════════════════════════════════════════════════════════
   HAVRO — shared stylesheet
   Nordic botanical drink · concept site by UpNorth
═══════════════════════════════════════════════════════════════════════ */

/* ── TOKENS ────────────────────────────────────────────────────────── */
:root {
  --color-cream:      #F5F0E8;
  --color-sand:       #E8DFD0;
  --color-warm-white: #FAF7F2;
  --color-charcoal:   #1E1E1A;
  --color-ink:        #0F0F0D;
  --color-text-muted: #6B6860;
  --color-evening:    #1A2E3A;
  --color-havtorn:    #E89048;
  --color-skog:       #7A9B7E;
  --color-skymning:   #9098B8;

  --font-display: 'Instrument Serif', Georgia, 'Times New Roman', serif;
  --font-body:    'Geist', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;

  --max-width: 1240px;
  --nav-h: 68px;

  --pad-tight:   clamp(48px, 6vw, 80px);
  --pad-normal:  clamp(72px, 9vw, 112px);
  --pad-breathe: clamp(112px, 14vw, 200px);

  --ease-calm:     cubic-bezier(0.22, 1, 0.36, 1);
  --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-quart:    cubic-bezier(0.76, 0, 0.24, 1);
  --ease-snap:     cubic-bezier(0.4, 0, 0.2, 1);
}

/* ── RESET ─────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; scroll-padding-top: var(--nav-h); background: var(--color-cream); }

:focus { outline: none; }
:focus-visible {
  outline: 2px solid var(--color-havtorn);
  outline-offset: 3px;
  border-radius: 2px;
}

body {
  background: var(--color-cream);
  color: var(--color-charcoal);
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 17px;
  line-height: 1.55;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
em { font-style: italic; }
img, video, canvas { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { border: none; background: none; cursor: pointer; font: inherit; color: inherit; }
ul, ol { list-style: none; }

/* ── LAYOUT PRIMITIVES ─────────────────────────────────────────────── */
.container {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0 clamp(24px, 5vw, 64px);
}
.container-narrow { max-width: 760px; margin: 0 auto; padding: 0 clamp(24px, 5vw, 64px); }

/* ── TYPOGRAPHY ────────────────────────────────────────────────────── */
.label-caps {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}
.display-xl {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(52px, 9vw, 136px);
  line-height: 0.98;
  letter-spacing: -0.025em;
}
.display-lg {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(40px, 6.5vw, 96px);
  line-height: 1.02;
  letter-spacing: -0.02em;
}
.display-md {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(32px, 4.5vw, 64px);
  line-height: 1.05;
  letter-spacing: -0.015em;
}
.display-sm {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(24px, 3vw, 36px);
  line-height: 1.15;
  letter-spacing: -0.01em;
}
.prose {
  font-size: clamp(16px, 1.3vw, 19px);
  line-height: 1.65;
  color: var(--color-charcoal);
}
.prose-muted {
  font-size: clamp(16px, 1.3vw, 19px);
  line-height: 1.65;
  color: var(--color-text-muted);
}
.editorial-italic {
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(20px, 2.2vw, 28px);
  line-height: 1.35;
  color: var(--color-charcoal);
}

/* ── BUTTONS ───────────────────────────────────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 16px 26px;
  border-radius: 2px;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  transition: background-color 480ms var(--ease-out-expo),
              color 480ms var(--ease-out-expo),
              border-color 480ms var(--ease-out-expo),
              padding 520ms var(--ease-out-expo),
              transform 520ms var(--ease-out-expo);
  min-height: 48px;
  position: relative;
  white-space: nowrap;
}
.btn__arrow {
  display: inline-block;
  font-family: var(--font-body);
  font-size: 14px;
  transition: transform 520ms var(--ease-out-expo);
}
.btn:hover { padding-right: 34px; }
.btn:hover .btn__arrow { transform: translateX(6px); }
.btn-primary {
  background: var(--color-charcoal);
  color: var(--color-cream);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.08),
              inset 0 -1px 0 rgba(0,0,0,0.3);
}
.btn-primary:hover { background: #2a2a24; }
.btn-accent {
  background: var(--color-havtorn);
  color: var(--color-charcoal);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.25);
}
.btn-accent:hover { background: #ec9d5a; }
.btn-outline-cream {
  background: transparent;
  border: 1px solid rgba(250,247,242,0.45);
  color: var(--color-cream);
}
.btn-outline-cream:hover { background: rgba(250,247,242,0.06); border-color: var(--color-cream); }
.btn-ghost {
  background: transparent;
  border: 1px solid var(--color-charcoal);
  color: var(--color-charcoal);
}
.btn-ghost:hover { background: var(--color-charcoal); color: var(--color-cream); }

/* Text link with underline reveal */
.link-underline {
  position: relative;
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  font-family: var(--font-body);
  font-size: 14px;
  letter-spacing: 0.02em;
  padding-bottom: 3px;
  color: inherit;
}
.link-underline::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background: currentColor;
  transform-origin: right;
  transform: scaleX(0);
  transition: transform 520ms var(--ease-out-expo);
}
.link-underline:hover::after { transform-origin: left; transform: scaleX(1); }

/* ── LIQUID GLASS ──────────────────────────────────────────────────── */
.liquid-glass {
  position: relative;
  backdrop-filter: blur(14px) saturate(150%);
  -webkit-backdrop-filter: blur(20px) saturate(160%);
  box-shadow: none;
}

/* ── GRAIN OVERLAY (hides ultrawide video pixelation) ───────────────── */
.grain {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 3;
  mix-blend-mode: overlay;
  opacity: 0.14;
  background-image: url("data:image/svg+xml;utf8,<svg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.92 0 0 0 0 0.88 0 0 0 0 0.80 0 0 0 0.5 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
  background-size: 200px 200px;
}
.grain--subtle { opacity: 0.08; }

/* ── MOTION UTILITIES ──────────────────────────────────────────────── */
/* Block reveal — fade + rise */
.reveal {
  opacity: 0;
  transform: translateY(32px);
  transition: opacity 900ms var(--ease-out-expo),
              transform 900ms var(--ease-out-expo);
  transition-delay: calc(var(--delay, 0) * 1ms);
}
.reveal.is-in { opacity: 1; transform: translateY(0); }

/* Stagger children (pair with .reveal on each child + --i) */
.reveal[style*="--i"] { transition-delay: calc(var(--i, 0) * 90ms); }

/* Word-by-word text reveal (parent gets .text-reveal, JS wraps each word in .word) */
.text-reveal { display: block; }
.text-reveal .line {
  display: block;
  overflow: hidden;
  padding-bottom: 0.12em;
  margin-bottom: -0.12em;
}
.text-reveal .word {
  display: inline-block;
  transform: translateY(105%);
  transition: transform 1100ms var(--ease-out-expo);
  transition-delay: calc(var(--wi, 0) * 55ms);
}
.text-reveal.is-in .word { transform: translateY(0); }

/* Char fade (for subtitles / captions) */
.text-fade .char {
  opacity: 0;
  display: inline-block;
  transition: opacity 700ms var(--ease-out-expo);
  transition-delay: calc(var(--ci, 0) * 18ms);
}
.text-fade.is-in .char { opacity: 1; }

/* Float gentle */
@keyframes havro-float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-12px); } }
.float { animation: havro-float 7s ease-in-out infinite; }

/* Slow rotate (for circular accents) */
@keyframes havro-rotate { to { transform: rotate(360deg); } }
.spin-slow { animation: havro-rotate 40s linear infinite; }

/* Marquee
   Two identical spans bound to the same data-copy key. Track translates
   from 0 to -50% so one span-width is "consumed" per loop and the
   second span seamlessly takes its place. flex-shrink:0 + identical
   spans + -50% keyframe = no visible gap before restart. */
.marquee {
  overflow: hidden;
  position: relative;
  mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
}
.marquee-track {
  display: flex;
  gap: 0;
  width: max-content;
  animation: marquee-x 60s linear infinite;
  will-change: transform;
}
.marquee-track > span {
  padding-right: 0;
  white-space: nowrap;
  flex: 0 0 auto;
}
@keyframes marquee-x {
  0%   { transform: translate3d(0, 0, 0); }
  100% { transform: translate3d(-50%, 0, 0); }
}

/* Clip reveal (left to right) */
.clip-reveal { clip-path: inset(0 100% 0 0); transition: clip-path 1400ms var(--ease-out-expo); }
.clip-reveal.is-in { clip-path: inset(0 0% 0 0); }

/* Blur in */
.blur-in { filter: blur(12px); opacity: 0; transition: filter 1100ms var(--ease-out-expo), opacity 1100ms var(--ease-out-expo); }
.blur-in.is-in { filter: blur(0); opacity: 1; }

/* Magnetic (JS applies transform) */
[data-magnetic] { transition: transform 400ms var(--ease-out-expo); }
[data-magnetic]:hover { transition-duration: 120ms; }

/* Fade-up alias */
.fade-up {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 800ms var(--ease-out-expo), transform 800ms var(--ease-out-expo);
  transition-delay: calc(var(--delay, 0) * 1ms);
}
.fade-up[style*="--i"] { transition-delay: calc(var(--i, 0) * 90ms); }
.fade-up.is-in { opacity: 1; transform: translateY(0); }

/* Scale-in (for images) */
.scale-in {
  opacity: 0;
  transform: scale(0.96);
  transition: opacity 900ms var(--ease-out-expo), transform 1200ms var(--ease-out-expo);
  transition-delay: calc(var(--delay, 0) * 1ms);
}
.scale-in.is-in { opacity: 1; transform: scale(1); }

/* Blur-in delay */
.blur-in { transition-delay: calc(var(--delay, 0) * 1ms); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
  }
  .reveal, .fade-up, .blur-in, .scale-in, .clip-reveal { opacity: 1 !important; transform: none !important; filter: none !important; clip-path: none !important; }
  .text-reveal .word { transform: none !important; }
  .text-fade .char { opacity: 1 !important; }
  .float, .spin-slow, .marquee-track { animation: none !important; }
}

/* ── CONCEPT RIBBON (demo framing) ─────────────────────────────────── */
.concept-ribbon {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 99;
  background: var(--color-ink);
  color: rgba(245,240,232,0.78);
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.08em;
  padding: 7px 0;
  text-align: center;
  font-weight: 400;
  transition: transform 480ms var(--ease-out-expo);
}
.concept-ribbon em { font-family: var(--font-display); font-style: italic; color: var(--color-havtorn); font-size: 13px; }
.concept-ribbon a { color: var(--color-cream); border-bottom: 1px solid rgba(245,240,232,0.3); padding-bottom: 1px; }
.concept-ribbon a:hover { border-bottom-color: var(--color-havtorn); }

/* When nav is scrolled, ribbon hides to reduce clutter */
body.nav-scrolled .concept-ribbon { transform: translateY(-100%); }

/* Mobile: keep the ribbon on a single line so it doesn't double-stack
   under the nav and crowd the logo. Smaller type, tighter spacing. */
@media (max-width: 720px) {
  .concept-ribbon {
    font-size: 9.5px;
    letter-spacing: 0.04em;
    padding: 6px 12px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .concept-ribbon em { font-size: 10.5px; }
}

/* ── NAV ───────────────────────────────────────────────────────────── */
.nav {
  position: fixed;
  top: 30px; left: 0; right: 0;
  z-index: 100;
  height: var(--nav-h);
  display: flex;
  align-items: center;
  transition: background 420ms var(--ease-out-expo),
              backdrop-filter 420ms var(--ease-out-expo),
              box-shadow 420ms var(--ease-out-expo),
              top 480ms var(--ease-out-expo),
              border-color 420ms var(--ease-out-expo);
  border-bottom: none;
}
/* After scroll: ribbon slides up, nav moves to top and gains glass */
body.nav-scrolled .nav {
  top: 0;
  background: rgba(245,240,232,0.78);
  backdrop-filter: blur(20px) saturate(160%);
  -webkit-backdrop-filter: blur(20px) saturate(160%);
  border: none;
  box-shadow: none;
}
/* When the nav is over a dark section while scrolled, swap the glass
   tint to ink so the cream icons remain readable. */
body.nav-scrolled.nav-on-dark .nav {
  background: rgba(15,15,13,0.55);
}
/* Pages with light hero get dark nav text even when not scrolled */
body.theme-light .nav { background: transparent; }
body.theme-light .nav .nav-logo,
body.theme-light .nav .nav-links a,
body.theme-light .nav .lang-btn { color: var(--color-charcoal); }
body.theme-light .nav .lang-sep { background: var(--color-sand); }

.nav .container { width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 32px; }
.nav-logo {
  font-family: var(--font-display);
  font-size: 26px;
  color: var(--color-warm-white);
  letter-spacing: 0.01em;
  line-height: 1;
}
body.nav-scrolled .nav .nav-logo { color: var(--color-charcoal); }
.nav-logo sup { font-size: 0.4em; vertical-align: super; font-family: var(--font-body); margin-left: 2px; color: var(--color-havtorn); }

.nav-links {
  display: flex;
  gap: 30px;
}
.nav-links a {
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 400;
  letter-spacing: 0.02em;
  color: rgba(250,247,242,0.82);
  transition: color 220ms var(--ease-out-expo);
  position: relative;
  padding: 6px 0;
}
.nav-links a::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: right;
  transition: transform 480ms var(--ease-out-expo);
}
.nav-links a:hover::after,
.nav-links a.active::after { transform: scaleX(1); transform-origin: left; }
body.nav-scrolled .nav .nav-links a { color: var(--color-charcoal); }
.nav-links a.active { color: var(--color-havtorn) !important; }

/* Adaptive nav: when the slice of page under the nav is on a dark
   section (set by JS via [data-nav-bg="dark"]), force the nav back
   to cream so it stays legible. Wins over .nav-scrolled because it
   ships later in the cascade. */
body.nav-on-dark .nav .nav-logo,
body.nav-on-dark .nav .nav-links a,
body.nav-on-dark .nav .lang-btn { color: var(--color-warm-white); }
body.nav-on-dark .nav .lang-sep { background: rgba(245,240,232,0.3); }
body.nav-on-dark .nav .hamburger span { background: var(--color-warm-white); }
body.nav-on-dark .nav .nav-links a.active { color: var(--color-havtorn) !important; }

/* Orange UpNorth highlight (used in the about page paragraph).
   Inherits font, size and weight from the surrounding paragraph so it
   reads as a tinted word, not a small caps link. */
.upnorth-mark {
  color: var(--color-havtorn) !important;
  font-family: inherit !important;
  font-size: inherit !important;
  font-weight: inherit !important;
  letter-spacing: inherit !important;
  padding-bottom: 0 !important;
  /* Keep .link-underline reveal but use the orange tint. */
}
.upnorth-mark::after { background: var(--color-havtorn) !important; }

.nav-right { display: flex; align-items: center; gap: 16px; }
.nav-lang { display: flex; align-items: center; gap: 10px; }
.lang-btn {
  font-family: var(--font-body);
  font-size: 12px;
  letter-spacing: 0.1em;
  color: rgba(250,247,242,0.55);
  transition: color 220ms var(--ease-out-expo);
  padding: 4px 2px;
}
.lang-btn.active { color: var(--color-warm-white); }
body.nav-scrolled .nav .lang-btn { color: var(--color-text-muted); }
body.nav-scrolled .nav .lang-btn.active { color: var(--color-charcoal); }
/* When the nav sits over a dark section the lang switcher needs to stay
   on a cream/orange palette — the default scrolled state turns the inactive
   side near-black which disappears against ink. */
body.nav-on-dark .nav .lang-btn { color: rgba(245,240,232,0.6); }
body.nav-on-dark .nav .lang-btn.active { color: var(--color-warm-white); }
.lang-sep { width: 1px; height: 12px; background: rgba(250,247,242,0.3); }

.hamburger { display: none; flex-direction: column; gap: 5px; padding: 8px; }
.hamburger span { width: 22px; height: 1.5px; background: var(--color-warm-white); transition: transform 320ms var(--ease-out-expo), opacity 320ms var(--ease-out-expo); }
body.nav-scrolled .hamburger span { background: var(--color-charcoal); }
.hamburger.open span:nth-child(1) { transform: translateY(6.5px) rotate(45deg); }
.hamburger.open span:nth-child(2) { opacity: 0; }
.hamburger.open span:nth-child(3) { transform: translateY(-6.5px) rotate(-45deg); }

.mobile-menu {
  position: fixed;
  inset: 0;
  background: var(--color-cream);
  z-index: 98;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 0 32px;
  transform: translateY(-100%);
  transition: transform 520ms var(--ease-out-expo);
  /* Prevent touch scroll inside the menu from bleeding through to the
     underlying page once the menu hits its scroll edge. */
  overscroll-behavior: contain;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
.mobile-menu.open { transform: translateY(0); }
/* While the menu is open, also lock the html node so iOS Safari doesn't
   keep scrolling the underlying page when the menu is at its top edge. */
html.menu-open, html.menu-open body { overflow: hidden !important; touch-action: none; }
.mobile-menu a { font-family: var(--font-display); font-size: 44px; color: var(--color-charcoal); padding: 14px 0; border-bottom: 1px solid var(--color-sand); }
.mobile-menu-lang { margin-top: 40px; display: flex; gap: 14px; }
/* Demo / studio credit pinned to the bottom of the mobile menu, in the
   same spirit as the studio footer credits used on upnorth.ax / fotomassage.ax. */
.mobile-menu-credit {
  position: absolute;
  left: 32px;
  right: 32px;
  bottom: calc(env(safe-area-inset-bottom, 0px) + 24px);
  padding: 16px 0 0;
  font-family: var(--font-body);
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  border-bottom: none !important;
  display: flex;
  align-items: center;
  gap: 8px;
}
.mobile-menu-credit strong {
  font-weight: 500;
  color: var(--color-charcoal);
  letter-spacing: 0.04em;
  text-transform: none;
  font-size: 13px;
}

/* ── HERO ──────────────────────────────────────────────────────────── */
.hero {
  position: relative;
  min-height: 100vh;
  min-height: 100svh;
  overflow: hidden;
  background: var(--color-ink);
}
/* Desktop: pin the hero text into the empty top-left "sky" zone so the
   centre cans stay clean. The container is forced flush-left with no
   max-width cap. */
@media (min-width: 721px) {
  .hero .container {
    position: absolute;
    top: clamp(140px, 22vh, 240px);
    left: clamp(20px, 3vw, 56px);
    right: auto;
    max-width: min(440px, 38vw);
    padding: 0;
    margin: 0;
    z-index: 4;
  }
}
@media (max-width: 720px) {
  /* Mobile: revert to a flex column anchored at the bottom over the
     darker vignette. Extra bottom padding keeps the sub line clear of
     the browser chrome. */
  .hero { display: flex; align-items: flex-end; padding-bottom: clamp(56px, 12vh, 96px); padding-top: 120px; }
  .hero .container { width: 100%; }
}
.hero-video {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  z-index: 1;
  filter: contrast(1.04) saturate(1.08) brightness(0.95);
  /* Hide ultrawide pixelation a little */
  transform: scale(1.02);
}
/* Static hero image: drop the masking filters, add slow ken-burns drift. */
.hero-still {
  filter: none;
  transform: scale(1.06);
  animation: heroDrift 14s ease-in-out infinite alternate;
}
@keyframes heroDrift {
  0%   { transform: scale(1.06) translate(0, 0); }
  100% { transform: scale(1.12) translate(-1.6%, -1.0%); }
}
@media (prefers-reduced-motion: reduce) {
  .hero-still { animation: none; transform: scale(1.04); }
}
.hero-vignette {
  position: absolute;
  inset: 0;
  z-index: 2;
  background:
    radial-gradient(120% 80% at 50% 55%, transparent 0%, rgba(15,15,13,0.32) 60%, rgba(15,15,13,0.7) 100%),
    linear-gradient(180deg, rgba(15,15,13,0.25) 0%, rgba(15,15,13,0) 30%, rgba(15,15,13,0) 65%, rgba(15,15,13,0.55) 100%);
}
/* Hero content lives in a left column so the cans (centre) breathe.
   Text-align is left and the column is capped so it can't drift over
   the centerpiece. */
.hero-content {
  position: relative;
  z-index: 4;
  width: 100%;
  text-align: left;
}
.hero-content > * { max-width: 100%; margin-left: 0; }
.hero-content .hero-h1 { max-width: 11ch; }
/* Mobile-only padding on the hero container — desktop is handled by
   the absolute pin further up. */
@media (max-width: 720px) {
  .hero .container { padding-left: clamp(20px, 5vw, 32px); padding-right: clamp(20px, 5vw, 32px); }
}
@media (max-width: 720px) {
  .hero .hero-h1 { font-size: clamp(36px, 9.5vw, 56px); max-width: none; overflow-wrap: break-word; }
  .hero .hero-content > * { max-width: 92vw; }
  /* Stronger bottom gradient on mobile so the headline reads cleanly
     over a tightly-cropped portrait of the cans. */
  .hero .hero-vignette {
    background:
      radial-gradient(120% 80% at 50% 30%, transparent 0%, rgba(15,15,13,0.30) 70%),
      linear-gradient(180deg, rgba(15,15,13,0.10) 0%, rgba(15,15,13,0) 30%, rgba(15,15,13,0.55) 70%, rgba(15,15,13,0.85) 100%);
  }
  /* Quieter eyebrow on mobile — the orange dash + caps was too loud
     above an already-small headline. */
  .hero .hero-eyebrow {
    font-size: 10px;
    letter-spacing: 0.16em;
    margin-bottom: 14px;
  }
  .hero .hero-eyebrow::before { width: 16px; }
}
.hero-eyebrow {
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(245,240,232,0.62);
  margin-bottom: 20px;
  display: inline-flex;
  align-items: center;
  gap: 10px;
}
.hero-eyebrow::before { content: ''; display: inline-block; width: 24px; height: 1px; background: var(--color-havtorn); }
.hero-h1 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(40px, 5.6vw, 92px);
  line-height: 0.98;
  letter-spacing: -0.025em;
  color: var(--color-cream);
  margin-bottom: 28px;
  max-width: 14ch;
}
/* Ultrawide bump: scale the hero title up further once we cross 1700px
   so it doesn't feel small in the negative space on 21:9 / 32:9 panels. */
@media (min-width: 1700px) {
  .hero-content .hero-h1 { font-size: clamp(72px, 5.4vw, 104px); }
  .hero-content { max-width: min(560px, 42vw) !important; }
}
.hero-h1 em { font-style: italic; color: rgba(245,240,232,0.55); }
.hero-sub {
  font-size: clamp(16px, 1.3vw, 18px);
  color: rgba(245,240,232,0.78);
  line-height: 1.55;
  margin-bottom: 40px;
  max-width: 42ch;
}
.hero-ctas { display: flex; gap: 14px; flex-wrap: wrap; }

.hero-scroll-cue {
  position: absolute;
  left: 50%;
  bottom: 28px;
  transform: translateX(-50%);
  z-index: 4;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  color: rgba(245,240,232,0.6);
  font-family: var(--font-body);
  font-size: 10px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
}
.hero-scroll-cue-line {
  width: 1px; height: 40px;
  background: rgba(245,240,232,0.3);
  position: relative;
  overflow: hidden;
}
.hero-scroll-cue-line::after {
  content: '';
  position: absolute;
  top: -40px; left: 0; right: 0; height: 40px;
  background: rgba(245,240,232,0.95);
  animation: scroll-cue 2.4s ease-in-out infinite;
}
@keyframes scroll-cue { 0% { transform: translateY(0); } 100% { transform: translateY(80px); } }

/* Page hero (inner page) — lighter, smaller */
.page-hero {
  position: relative;
  padding: calc(var(--nav-h) + 100px) 0 80px;
  background: var(--color-cream);
}
.page-hero-eyebrow {
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  margin-bottom: 20px;
  display: inline-flex;
  gap: 10px;
  align-items: center;
}
.page-hero-eyebrow::before {
  content: '';
  display: inline-block;
  width: 24px; height: 1px;
  background: var(--color-havtorn);
}
.page-hero-h1 {
  font-family: var(--font-display);
  font-size: clamp(52px, 8.5vw, 128px);
  line-height: 1;
  letter-spacing: -0.025em;
  color: var(--color-charcoal);
  margin-bottom: 24px;
  max-width: 14ch;
}
.page-hero-h1 em { font-style: italic; color: var(--color-havtorn); }
.page-hero-sub {
  font-size: clamp(16px, 1.4vw, 20px);
  color: var(--color-text-muted);
  line-height: 1.6;
  max-width: 54ch;
}

/* ── HOME: PORTAL CARDS ────────────────────────────────────────────── */
.portals {
  padding: var(--pad-breathe) 0 var(--pad-normal);
  background: var(--color-cream);
}
.portals-head {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 48px;
  align-items: end;
  margin-bottom: 80px;
}
.portals-head h2 { max-width: 14ch; }
.portals-head p { max-width: 38ch; color: var(--color-text-muted); font-size: 17px; line-height: 1.6; }
.portal-grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 24px;
}
.portal {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  overflow: hidden;
  border-radius: 2px;
  background: var(--color-warm-white);
  aspect-ratio: 4 / 5;
  padding: 32px;
  color: var(--color-cream);
  isolation: isolate;
  transition: transform 720ms var(--ease-out-expo);
}
.portal-1 { grid-column: span 7; aspect-ratio: 5 / 4; }
.portal-2 { grid-column: span 5; aspect-ratio: 4 / 5; }
.portal-3 { grid-column: span 5; aspect-ratio: 4 / 5; }
.portal-4 { grid-column: span 7; aspect-ratio: 5 / 4; }
.portal-media {
  position: absolute;
  inset: 0;
  z-index: 0;
}
.portal-media img, .portal-media video, .portal-media canvas {
  width: 100%; height: 100%;
  object-fit: cover;
  transform: scale(1.04);
  transition: transform 1400ms var(--ease-out-expo), filter 800ms var(--ease-out-expo);
}
.portal::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(180deg, rgba(0,0,0,0) 40%, rgba(15,15,13,0.75) 100%);
  transition: opacity 600ms var(--ease-out-expo);
}
.portal-body { position: relative; z-index: 2; }
.portal-num {
  font-family: var(--font-display);
  font-style: italic;
  font-size: 48px;
  color: var(--color-havtorn);
  line-height: 1;
  margin-bottom: 40px;
  display: block;
  letter-spacing: -0.02em;
}
.portal-title {
  font-family: var(--font-display);
  font-size: clamp(28px, 3.5vw, 44px);
  line-height: 1.05;
  letter-spacing: -0.015em;
  margin-bottom: 8px;
}
.portal-desc {
  font-family: var(--font-display);
  font-style: italic;
  font-size: 18px;
  color: rgba(245,240,232,0.85);
  margin-bottom: 18px;
  max-width: 28ch;
}
.portal-arrow {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-body);
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  white-space: nowrap;
}
.portal-arrow > span:first-child {
  display: inline-block;
  width: 18px;
  height: 1px;
  background: currentColor;
  flex: 0 0 auto;
  transition: width 520ms var(--ease-out-expo);
}
.portal-arrow > span:last-child {
  display: inline-block;
  width: auto;
  height: auto;
  background: transparent;
  line-height: 1.1;
  white-space: nowrap;
}
.portal:hover .portal-arrow > span:first-child { width: 32px; }
.portal:hover .portal-media img, .portal:hover .portal-media video, .portal:hover .portal-media canvas { transform: scale(1.10); }
/* Ken-burns drift on still images so they feel alive next to the autoplay videos.
   `animation-fill-mode: both` keeps the start frame consistent with our static
   `transform: scale(1.04)` so portal-4 doesn't snap on first paint. */
.portal-media img {
  animation: kenburns 14s ease-in-out infinite alternate both;
}
@media (prefers-reduced-motion: reduce) { .portal-media img { animation: none; } }

/* ── MANIFESTO (home) ─────────────────────────────── */
.manifesto {
  background: var(--color-ink);
  color: var(--color-cream);
  padding: clamp(96px, 14vh, 160px) 0;
  border-top: 1px solid rgba(245,240,232,0.08);
  border-bottom: 1px solid rgba(245,240,232,0.08);
}
.manifesto .label-caps {
  color: rgba(245,240,232,0.55);
  margin-bottom: 28px;
  display: inline-flex;
  align-items: center;
  gap: 10px;
}
.manifesto .label-caps::before {
  content: ''; display: inline-block; width: 24px; height: 1px; background: var(--color-havtorn);
}
.manifesto-quote {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(34px, 4.4vw, 64px);
  line-height: 1.08;
  letter-spacing: -0.018em;
  max-width: 22ch;
  margin: 0 0 32px;
}
.manifesto-quote em { font-style: italic; color: var(--color-havtorn); }
.manifesto-meta {
  font-family: var(--font-body);
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(245,240,232,0.6);
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
}
.manifesto-meta .dot { color: var(--color-havtorn); opacity: 0.7; }

/* ── FLAVOUR PREVIEW (home) ─────────────────────── */
.flavour-preview {
  background: var(--color-cream);
  color: var(--color-ink);
  padding: clamp(96px, 14vh, 160px) 0;
}
.flavour-preview-head {
  display: grid;
  grid-template-columns: 1fr 2fr;
  gap: 48px;
  align-items: end;
  margin-bottom: 64px;
}
.flavour-preview-list {
  list-style: none;
  margin: 0; padding: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 32px;
}
.flavour-preview-item {
  display: flex;
  flex-direction: column;
  gap: 24px;
}
.flavour-preview-imgwrap {
  position: relative;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  background: rgba(30,30,26,0.04);
  border-radius: 2px;
}
.flavour-preview-imgwrap img {
  width: 100%; height: 100%;
  object-fit: cover;
  transform: scale(1.04);
  transition: transform 1400ms var(--ease-out-expo);
  animation: kenburns 11s ease-in-out infinite alternate;
}
.flavour-preview-item:nth-child(2) .flavour-preview-imgwrap img { animation-delay: -4s; }
.flavour-preview-item:nth-child(3) .flavour-preview-imgwrap img { animation-delay: -7s; }
.flavour-preview-item:hover .flavour-preview-imgwrap img { transform: scale(1.10); }
@keyframes kenburns {
  0%   { transform: scale(1.04) translate(0, 0); }
  100% { transform: scale(1.14) translate(-2.5%, -2%); }
}
@media (prefers-reduced-motion: reduce) {
  .flavour-preview-imgwrap img { animation: none; }
}

/* Title hover float — used on cards/portals/manifesto */
.title-hover {
  display: inline-block;
  transition: transform 480ms var(--ease-out-expo), color 320ms ease;
}
.title-hover-host:hover .title-hover { transform: translateY(-3px); }
.flavour-card:hover .flavour-card-name,
.flavour-preview-item:hover .flavour-preview-name,
.portal:hover .portal-title {
  transform: translateY(-3px);
  transition: transform 520ms var(--ease-out-expo);
}
.flavour-card-name, .flavour-preview-name, .portal-title {
  display: inline-block;
  will-change: transform;
  transition: transform 520ms var(--ease-out-expo);
}
.flavour-preview-num {
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--color-havtorn);
}
.flavour-preview-name {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(22px, 2vw, 28px);
  line-height: 1.1;
  letter-spacing: -0.01em;
  margin: 8px 0 6px;
}
.flavour-preview-desc {
  font-size: 14px;
  color: var(--color-text-muted);
  line-height: 1.55;
}
.flavour-preview-cta {
  display: inline-flex;
  margin-top: 56px;
  gap: 10px;
  font-size: 14px;
  letter-spacing: 0.04em;
}
@media (max-width: 768px) {
  .flavour-preview-head { grid-template-columns: 1fr; gap: 16px; }
  .flavour-preview-list { grid-template-columns: 1fr; gap: 28px; }
  .manifesto-quote { font-size: clamp(30px, 9vw, 44px); }
}

/* ── KEN-BURNS STILL (ingredients intro film strip) ─────────────────
   Slow scale + drift on a static webp. Gives the same "always-moving"
   feel as the old looping video but at a fraction of the bytes. */
.ing-intro-media--still { background: var(--color-ink); }
.ing-intro-still {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
  transform-origin: 50% 50%;
  animation: ingStillDrift 22s ease-in-out infinite alternate;
  will-change: transform;
  filter: contrast(1.05) saturate(1.04);
}
@keyframes ingStillDrift {
  0%   { transform: scale(1.06) translate3d(-1.2%, -0.6%, 0); }
  100% { transform: scale(1.14) translate3d( 1.4%,  0.8%, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .ing-intro-still { animation: none; transform: scale(1.04); }
}

/* ── INTRO STRIP (home, below portals) ─────────────────────────────── */
.marquee-strip {
  padding: 32px 0;
  border-top: 1px solid var(--color-sand);
  border-bottom: 1px solid var(--color-sand);
  background: var(--color-warm-white);
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(28px, 4vw, 52px);
  color: var(--color-charcoal);
}
.marquee-strip .dot { color: var(--color-havtorn); margin: 0 24px; font-style: normal; }

/* Inset variant: when the marquee lives inside .portals-head (under the
   chapter title) we shrink the type and drop the section borders so it
   reads as a quiet ribbon rather than a full-bleed strip. */
.marquee-strip--inset {
  margin-top: clamp(24px, 4vh, 48px);
  margin-bottom: clamp(40px, 7vh, 80px);
  padding: 18px 0;
  border-top: 1px solid var(--color-sand);
  border-bottom: 1px solid var(--color-sand);
  background: transparent;
  font-size: clamp(20px, 2.6vw, 32px);
  color: var(--color-charcoal);
}
.marquee-strip--inset .dot { margin: 0 18px; }

/* ── DRYCKEN: SHOWCASE (rebuilt — no PowerPoint box) ─────────────────
   IMPORTANT: do NOT set overflow:hidden on the section — that breaks
   `position: sticky` on .showcase-sticky and causes the canvas to
   scroll past while the captions stay visible. */
.showcase {
  position: relative;
  background: var(--color-ink);
  color: var(--color-cream);
}
.showcase-sticky {
  position: sticky;
  top: 0;
  height: var(--showcase-vh, 100vh);
  overflow: hidden;
}
.showcase-canvas {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  display: block;
  z-index: 1;
  opacity: 0;
  transition: opacity 800ms var(--ease-out-expo);
  filter: contrast(1.04) saturate(1.08);
}
.showcase-canvas.ready { opacity: 1; }
.showcase-video {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  /* contain (not cover) so the full can is visible on ultrawide displays.
     The source clip is composed for 16:9 with deliberate breathing
     room top/bottom — cover was eating that intentional negative space. */
  object-fit: contain;
  object-position: center;
  z-index: 1;
  filter: contrast(1.04) saturate(1.08);
  background: var(--color-ink);
}
.showcase-vignette {
  position: absolute;
  inset: 0;
  z-index: 2;
  background:
    linear-gradient(90deg, rgba(15,15,13,0.72) 0%, rgba(15,15,13,0.2) 45%, rgba(15,15,13,0) 70%),
    linear-gradient(180deg, rgba(15,15,13,0.3) 0%, rgba(15,15,13,0) 40%, rgba(15,15,13,0) 70%, rgba(15,15,13,0.5) 100%);
}
.showcase-caption-area {
  position: absolute;
  inset: 0;
  z-index: 4;
  display: flex;
  align-items: center;
  padding: 0 clamp(32px, 8vw, 96px);
}
.showcase-captions {
  max-width: 520px;
  position: relative;
  min-height: 240px;
}
/* Ultrawide widens the caption block so headlines never collapse to one
   word per line. At 1700px+ a 520px column with 68px serif type was
   wrapping "Birch / for / a / clean / Nordic / tone." vertically. */
@media (min-width: 1400px) { .showcase-captions { max-width: 720px; } }
@media (min-width: 1900px) { .showcase-captions { max-width: 880px; } }
.showcase-caption {
  position: absolute;
  inset: 0;
  opacity: 0;
  transform: translateY(12px);
  transition: opacity 900ms var(--ease-out-expo), transform 900ms var(--ease-out-expo);
  pointer-events: none;
}
.showcase-caption.active { opacity: 1; transform: translateY(0); }
.showcase-caption-num {
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(245,240,232,0.55);
  margin-bottom: 20px;
  display: inline-flex;
  gap: 10px;
  align-items: center;
}
.showcase-caption-num::before {
  content: ''; width: 24px; height: 1px; background: var(--color-havtorn); display: inline-block;
}
.showcase-caption-text {
  font-family: var(--font-display);
  font-size: clamp(36px, 5.5vw, 68px);
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: var(--color-cream);
}
.showcase-caption-text em { font-style: italic; color: rgba(245,240,232,0.65); }

.showcase-progress {
  position: absolute;
  left: clamp(32px, 8vw, 96px);
  right: clamp(32px, 8vw, 96px);
  bottom: 56px;
  z-index: 4;
  height: 1px;
  background: rgba(245,240,232,0.18);
}
.showcase-progress-fill {
  height: 100%;
  width: 0%;
  background: var(--color-havtorn);
  transition: width 250ms linear;
}
.showcase-index {
  position: absolute;
  right: clamp(32px, 8vw, 96px);
  bottom: 24px;
  z-index: 4;
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.2em;
  color: rgba(245,240,232,0.6);
  text-transform: uppercase;
}

/* ── FLAVOURS ──────────────────────────────────────────────────────── */
.flavours {
  padding: var(--pad-normal) 0;
  background: var(--color-cream);
}
.flavours-head {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 48px;
  align-items: end;
  margin-bottom: 64px;
}
.flavours-head h2 { max-width: 16ch; }
.flavours-head p { max-width: 36ch; color: var(--color-text-muted); font-size: 16px; line-height: 1.6; }
.flavours-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
}
/* 2-card variant — used on ingredienser.html "Övriga smaker" where only
   the two non-Havtorn flavours are shown. Centred, narrower so they don't
   stretch the full container width. */
.flavours-grid--two {
  grid-template-columns: repeat(2, minmax(0, 380px));
  justify-content: center;
}
.flavour-card {
  background: var(--color-warm-white);
  border: 1px solid var(--color-sand);
  border-radius: 2px;
  overflow: hidden;
  transition: background-color 520ms var(--ease-out-expo),
              border-color 520ms var(--ease-out-expo);
}
.flavour-card:hover {
  background: var(--color-cream);
  border-color: var(--color-charcoal);
}
.flavour-card-imgwrap {
  aspect-ratio: 1;
  overflow: hidden;
  background: var(--color-sand);
  position: relative;
}
.flavour-card-imgwrap img {
  width: 100%; height: 100%;
  object-fit: cover;
  transform: scale(1.04);
  transition: transform 1400ms var(--ease-out-expo);
  animation: kenburns 12s ease-in-out infinite alternate;
}
.flavours-grid .flavour-card:nth-child(2) .flavour-card-imgwrap img { animation-delay: -4s; }
.flavours-grid .flavour-card:nth-child(3) .flavour-card-imgwrap img { animation-delay: -8s; }
.flavour-card:hover .flavour-card-imgwrap img { transform: scale(1.10); }
@media (prefers-reduced-motion: reduce) {
  .flavour-card-imgwrap img { animation: none; }
}
.flavour-card-stripe { height: 2px; }
.flavour-card-stripe.orange { background: var(--color-havtorn); }
.flavour-card-stripe.lavender { background: var(--color-skymning); }
.flavour-card-stripe.green { background: var(--color-skog); }
.flavour-card-body { padding: 24px 24px 28px; }
.flavour-card-num {
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.14em;
  color: var(--color-text-muted);
  margin-bottom: 14px;
  display: block;
}
.flavour-card-name {
  font-family: var(--font-display);
  font-size: clamp(26px, 2.4vw, 32px);
  line-height: 1.1;
  letter-spacing: -0.015em;
  margin-bottom: 8px;
}
.flavour-card-desc {
  font-size: 14px;
  color: var(--color-text-muted);
  line-height: 1.5;
}

/* ── INGREDIENTS SCROLLYTELLING (fixed aspect ratio) ───────────────── */
.ing-scroll {
  position: relative;
  background: var(--color-cream);
}
.ing-track {
  /* Each step gets ~60vh of scroll — fast enough to flow through the
     5 ingredients without feeling padded out. */
  position: relative;
  height: 320vh;
}
.ing-sticky {
  position: sticky;
  top: 0;
  height: 100vh;
  display: flex;
  align-items: center;
  overflow: hidden;
}
.ing-layout {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 80px;
  align-items: center;
  width: 100%;
}
.ing-steps {
  position: relative;
  padding-right: 24px;
}
.ing-indicator {
  position: absolute;
  right: -8px;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.ing-indicator span {
  width: 2px;
  height: 14px;
  background: rgba(30,30,26,0.18);
  transition: background 420ms var(--ease-out-expo), height 420ms var(--ease-out-expo);
  display: block;
}
.ing-indicator span.active {
  background: var(--color-havtorn);
  height: 28px;
}
.ing-header { margin-bottom: 48px; }
.ing-header .label-caps { margin-bottom: 12px; }
.ing-h2 {
  font-family: var(--font-display);
  font-size: clamp(26px, 3.4vw, 44px);
  line-height: 1.1;
  letter-spacing: -0.015em;
  max-width: 18ch;
}
.ing-step-stack { position: relative; min-height: 300px; }
.ing-step {
  position: absolute;
  inset: 0;
  opacity: 0;
  transform: translateY(18px);
  filter: blur(4px);
  transition:
    opacity 900ms var(--ease-out-expo),
    transform 900ms var(--ease-out-expo),
    filter 900ms var(--ease-out-expo);
  pointer-events: none;
  will-change: opacity, transform, filter;
}
.ing-step.active {
  opacity: 1;
  transform: translateY(0);
  filter: blur(0);
  pointer-events: auto;
}
.ing-step-num {
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.2em;
  color: var(--color-havtorn);
  margin-bottom: 16px;
  display: inline-block;
}
.ing-step-name {
  font-family: var(--font-display);
  font-size: clamp(48px, 7vw, 96px);
  line-height: 1;
  letter-spacing: -0.02em;
  margin-bottom: 20px;
}
.ing-step-desc {
  font-size: clamp(16px, 1.4vw, 19px);
  line-height: 1.55;
  color: var(--color-text-muted);
  max-width: 38ch;
}
.ing-step-meta {
  margin-top: 24px;
  font-family: var(--font-display);
  font-style: italic;
  font-size: 17px;
  color: var(--color-charcoal);
  line-height: 1.4;
  max-width: 38ch;
  opacity: 0.72;
}
.ing-step-meta::before { content: '— '; color: var(--color-havtorn); font-style: normal; }

/* Product box — FIXED aspect ratio 4:3 to match frames.
   Background kept as a flat warm-cream: any gradient mix with the
   greenish/blueish tint of the AI frames was reading as a cool tint. */
.product-box {
  position: relative;
  width: 100%;
  max-width: 560px;
  justify-self: end;
  aspect-ratio: 4 / 3;
  border-radius: 6px;
  overflow: hidden;
  background: var(--color-warm-white);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.7),
    inset 0 -1px 0 rgba(0,0,0,0.04),
    0 2px 2px rgba(30,30,26,0.03),
    0 24px 48px -20px rgba(30,30,26,0.18);
}
.product-box.product-box--lg { max-width: 680px; }
/* Square variant for the ingredient explosion (DAR 1:1 source). */
.product-box.product-box--square {
  max-width: 640px;
  aspect-ratio: 1 / 1;
}
.product-box canvas,
.product-box .product-video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  opacity: 0;
  transition: opacity 700ms var(--ease-out-expo);
}
.product-box canvas.ready,
.product-box .product-video.ready { opacity: 1; }
/* Static fallback (mobile / reduced-motion / decode failure) — same
   slot as the canvas, fades in once decoded. */
.product-box .product-fallback-img {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}

/* ── INGREDIENTS INTRO FILM STRIP ── */
.ing-intro {
  position: relative;
  background: var(--color-ink);
  color: var(--color-cream);
  /* Tighter than before — the gap to "Five ingredients. Nothing more."
     was reading as dead space. */
  margin-bottom: clamp(20px, 4vh, 48px);
}
.ing-intro-media {
  position: relative;
  width: 100%;
  aspect-ratio: 21 / 9;
  overflow: hidden;
  background: var(--color-ink);
}
.ing-intro-video {
  width: 100%; height: 100%;
  object-fit: cover;
  filter: saturate(1.05) contrast(1.04);
  transform: scale(1.04);
  animation: heroDrift 16s ease-in-out infinite alternate;
}
.ing-intro-vignette {
  position: absolute;
  inset: 0;
  /* Stronger darkening over the top-right corner so the caption text
     keeps contrast regardless of what's behind it in the still life. */
  background:
    radial-gradient(80% 60% at 100% 0%, rgba(15,15,13,0.55) 0%, rgba(15,15,13,0) 60%),
    radial-gradient(120% 80% at 50% 50%, transparent 30%, rgba(15,15,13,0.35) 100%),
    linear-gradient(180deg, rgba(15,15,13,0.25) 0%, rgba(15,15,13,0) 30%, rgba(15,15,13,0) 70%, rgba(15,15,13,0.4) 100%);
  pointer-events: none;
}
.ing-intro-caption {
  /* Pinned to the top-right corner of the media so the headline reads
     against the darker upper edge instead of overlapping the centre
     of the still life. Overrides the inherited .container width/padding
     because the caption is absolutely positioned now. */
  position: absolute;
  top: clamp(20px, 4vh, 48px);
  right: clamp(20px, 4vw, 56px);
  bottom: auto;
  left: auto;
  max-width: min(420px, 60vw);
  padding: 0;
  margin: 0;
  text-align: right;
  display: flex;
  flex-direction: column;
  gap: 14px;
  z-index: 2;
  pointer-events: none;
}
.ing-intro-caption .label-caps { color: rgba(245,240,232,0.7); justify-content: flex-end; }
.ing-intro-caption .label-caps::before { display: none; }
.ing-intro-caption .label-caps::after {
  content: ''; display: inline-block; width: 24px; height: 1px;
  background: var(--color-havtorn); margin-left: 10px; vertical-align: middle;
}
.ing-intro-text {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(24px, 3vw, 44px);
  line-height: 1.08;
  letter-spacing: -0.018em;
  color: var(--color-cream);
  max-width: 22ch;
  margin: 0;
  text-align: right;
  align-self: flex-end;
}
.ing-intro-text em { font-style: italic; color: var(--color-havtorn); }
@media (max-width: 768px) {
  /* Intro caption moves out of the top-right overlay on small screens
     and becomes a normal-flow block below the media. The 60vw cap was
     collapsing the italic headline into a 6-line stack on 360px wide
     phones. Normal flow lets it read as a proper caption. */
  .ing-intro-media { aspect-ratio: 4 / 5; }
  .ing-intro-caption {
    position: static;
    inset: auto;
    max-width: none;
    /* Generous breathing room around the dark caption block on mobile.
       Previous 64/28/80 still felt cramped against the section edges and
       the type pressed close to the side rails. Bumped to give the
       "Plockat, tappat, pressat. Inget hittat på." headline real space
       to breathe inside the dark band. */
    padding: 88px 36px 104px;
    text-align: left;
    align-items: flex-start;
    gap: 32px;
  }
  .ing-intro-caption .label-caps { justify-content: flex-start; }
  .ing-intro-caption .label-caps::after { display: none; }
  .ing-intro-caption .label-caps::before {
    content: ''; display: inline-block; width: 24px; height: 1px;
    background: var(--color-havtorn); margin-right: 10px; vertical-align: middle;
  }
  .ing-intro-text {
    text-align: left;
    align-self: flex-start;
    font-size: clamp(26px, 7vw, 36px);
    max-width: none;
  }
}
.product-box-badge {
  position: absolute;
  top: 18px; left: 18px;
  z-index: 3;
  font-family: var(--font-body);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  background: rgba(245,240,232,0.8);
  backdrop-filter: blur(6px);
  padding: 6px 10px;
  border-radius: 2px;
}
.product-box-meta {
  position: absolute;
  bottom: 18px; right: 18px;
  z-index: 3;
  font-family: var(--font-body);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  opacity: 0.6;
}
.product-box-loader {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-style: italic;
  font-size: 32px;
  color: var(--color-text-muted);
  transition: opacity 500ms var(--ease-out-expo);
}
.product-box-loader.hidden { opacity: 0; pointer-events: none; }
.product-box-progress {
  position: absolute;
  left: 18px; right: 18px;
  bottom: 10px;
  height: 1px;
  background: rgba(30,30,26,0.1);
  z-index: 3;
}
.product-box-progress-fill {
  height: 100%;
  width: 0%;
  background: var(--color-havtorn);
  transition: width 160ms linear;
}

/* ── PHILOSOPHY ────────────────────────────────────────────────────── */
.filosofi {
  padding: var(--pad-breathe) 0;
  background: var(--color-warm-white);
  position: relative;
}
.filosofi .container { max-width: 760px; }
.filosofi-accent {
  width: 40px;
  height: 1px;
  background: var(--color-havtorn);
  margin-bottom: 20px;
}
.filosofi-eyebrow {
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  margin-bottom: 40px;
}
.filosofi-h2 {
  font-family: var(--font-display);
  font-size: clamp(36px, 5.5vw, 72px);
  line-height: 1.05;
  letter-spacing: -0.02em;
  margin-bottom: 56px;
  max-width: 16ch;
}
.filosofi-h2 em { font-style: italic; color: var(--color-havtorn); }
.filosofi-prose p {
  font-size: clamp(17px, 1.4vw, 20px);
  line-height: 1.65;
  color: var(--color-charcoal);
  margin-bottom: 28px;
  max-width: 58ch;
}
.filosofi-closing {
  margin-top: 72px;
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(28px, 4vw, 44px);
  line-height: 1.2;
  color: var(--color-havtorn);
  max-width: 18ch;
}

/* ── LIFESTYLE ─────────────────────────────────────────────────────── */
.lifestyle {
  position: relative;
  padding: var(--pad-normal) 0;
  background: var(--color-ink);
  color: var(--color-cream);
  overflow: hidden;
  min-height: 100vh;
  display: flex;
  align-items: center;
}
.lifestyle-video {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  z-index: 1;
  opacity: 0.62;
  filter: grayscale(0.05) saturate(1.05);
  transform: scale(1.04);
  animation: heroDrift 18s ease-in-out infinite alternate;
}
/* Tunnel-vision: clear in centre, darker on the sides — the can stays the focus */
.lifestyle-overlay {
  position: absolute;
  inset: 0;
  z-index: 2;
  background:
    radial-gradient(70% 100% at 50% 50%, transparent 0%, rgba(15,15,13,0.05) 30%, rgba(15,15,13,0.55) 75%, rgba(15,15,13,0.85) 100%),
    linear-gradient(180deg, rgba(15,15,13,0.25) 0%, rgba(15,15,13,0) 25%, rgba(15,15,13,0) 70%, rgba(15,15,13,0.45) 100%);
}

/* SIDE variant (filosofi lifestyle) — STACKED LIGHT LAYOUT.
   Filosofi was the only page that flipped to a black section mid-
   scroll, which broke the rhythm of the rest of the site. The section
   now stays on the warm cream theme: cinematic 16:9 video block on
   top, then heading + 2×2 cards below in dark type on cream. Tone is
   preserved (it's still the quiet sauna photography) but the page
   reads as one continuous surface instead of three colour zones. */
.lifestyle--side {
  background: var(--color-cream);
  color: var(--color-charcoal);
  display: block;
  min-height: 0;
  padding: 0 0 var(--pad-normal);
  overflow: hidden;
}
.lifestyle--side .lifestyle-label { color: var(--color-text-muted); }
.lifestyle--side .lifestyle-h2 { color: var(--color-charcoal); }
.lifestyle--side .lifestyle-h2 em { color: var(--color-havtorn); }
.lifestyle--side .lifestyle-block-side { border-top-color: rgba(30,30,26,0.12); }
.lifestyle--side .lifestyle-block-label { color: var(--color-charcoal); }
.lifestyle--side .lifestyle-block-desc { color: var(--color-text-muted); }
.lifestyle--side .lifestyle-number { color: var(--color-havtorn); }
.lifestyle--side .lifestyle-video {
  position: relative;
  inset: auto;
  top: auto; right: auto; left: auto; bottom: auto;
  transform: none;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  opacity: 1;
  filter: saturate(1.05);
  animation: none;
  border-radius: 0;
  box-shadow: none;
  display: block;
  object-fit: cover;
  margin-bottom: clamp(40px, 7vh, 80px);
  /* Ink underlay so the moment between "poster shown" and "first video
     frame painted" doesn't flash a brighter still. The previous
     saunaafteroutside.webp poster is a different scene from the video
     and felt like a misplaced placeholder. Keep the video unposterised
     and let the ink bg + the natural fade-in feel intentional. */
  background-color: var(--color-ink);
}
.lifestyle--side .lifestyle-overlay { display: none; }
.lifestyle--side .container {
  position: relative;
  z-index: 3;
  display: block;
  max-width: 880px;          /* keep the column readable on wide screens */
}
.lifestyle--side .lifestyle-text-side--left { max-width: none; grid-column: auto; }
.lifestyle-text-side--right { display: none; }
.lifestyle-text-side { max-width: none; }
.lifestyle-label { color: rgba(245,240,232,0.7); margin-bottom: 20px; }
.lifestyle-label::before {
  content: ''; display: inline-block; width: 24px; height: 1px;
  background: var(--color-havtorn); margin-right: 10px; vertical-align: middle;
}
.lifestyle-h2 {
  font-family: var(--font-display);
  font-size: clamp(32px, 4.4vw, 56px);
  line-height: 1.05;
  letter-spacing: -0.02em;
  margin-bottom: 32px;
  max-width: 14ch;
}
.lifestyle-grid--side {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 32px;
  margin-top: 8px;
}
.lifestyle-block-side {
  border-top: 1px solid rgba(250,247,242,0.18);
  padding: 18px 0;
  display: grid;
  grid-template-columns: 32px 1fr;
  gap: 14px;
  align-items: baseline;
}
.lifestyle-block-side .lifestyle-number { font-size: 18px; margin-bottom: 0; line-height: 1; }
.lifestyle-block-side .lifestyle-block-label { margin-bottom: 4px; }
.lifestyle-block-side .lifestyle-block-desc { font-size: 13px; line-height: 1.5; }
@media (max-width: 720px) {
  .lifestyle--side .lifestyle-video { aspect-ratio: 4 / 3; margin-bottom: 32px; }
  .lifestyle-grid--side { grid-template-columns: 1fr; }
  .lifestyle-overlay {
    background: linear-gradient(180deg, rgba(15,15,13,0.55) 0%, rgba(15,15,13,0.78) 100%);
  }
}
.lifestyle-h2 em { font-style: italic; color: rgba(245,240,232,0.55); }
.lifestyle-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 40px 48px;
}
.lifestyle-block {
  border-top: 1px solid rgba(250,247,242,0.15);
  padding-top: 24px;
}
.lifestyle-number {
  display: block;
  font-family: var(--font-display);
  font-style: italic;
  font-size: 56px;
  color: var(--color-havtorn);
  line-height: 1;
  margin-bottom: 24px;
  letter-spacing: -0.02em;
}
.lifestyle-block-label {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 16px;
  color: var(--color-warm-white);
  margin-bottom: 6px;
}
.lifestyle-block-desc {
  font-size: 14px;
  color: rgba(250,247,242,0.72);
  line-height: 1.5;
}

/* ── POUR — full-bleed cinematic ───────────────────── */
.pour {
  position: relative;
  padding: 0;
  background: var(--color-ink);
  color: var(--color-cream);
  height: 100vh;
  min-height: 640px;
  overflow: hidden;
}
.pour-video-wrap {
  position: absolute;
  inset: 0;
  margin: 0;
  border-radius: 0;
  aspect-ratio: auto;
  background: var(--color-ink);
  overflow: hidden;
}
.pour-video-wrap video {
  width: 100%; height: 100%;
  object-fit: cover;
  filter: saturate(1.05);
}
.pour-overlay {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(120% 80% at 50% 50%, transparent 25%, rgba(15,15,13,0.55) 100%),
    linear-gradient(180deg, rgba(15,15,13,0.4) 0%, rgba(15,15,13,0) 35%, rgba(15,15,13,0) 60%, rgba(15,15,13,0.65) 100%);
  pointer-events: none;
}
.pour .container {
  position: relative;
  z-index: 2;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding-top: clamp(80px, 14vh, 140px);
  padding-bottom: clamp(56px, 10vh, 96px);
  gap: 0;
  grid-template-columns: none;
}
.pour-text { max-width: 540px; }
.pour-text .label-caps { color: rgba(245,240,232,0.7); margin-bottom: 24px; }
.pour-text .label-caps::before {
  content: ''; display: inline-block; width: 24px; height: 1px;
  background: var(--color-havtorn); margin-right: 10px; vertical-align: middle;
}
.pour-h2 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(48px, 7vw, 96px);
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--color-cream);
  margin: 0 0 24px;
}
.pour-h2 em { font-style: italic; color: rgba(245,240,232,0.6); }
.pour-body {
  font-size: clamp(15px, 1.15vw, 17px);
  color: rgba(245,240,232,0.78);
  line-height: 1.6;
  margin-bottom: 32px;
}

/* ── ABOUT ──────────────
   Was: text container + absolutely-positioned right image. That made
   the headline sit on top of the image at narrow desktop widths. Now:
   a CSS grid in .container (text left, image right) so they share
   space cleanly and stack on tablet/mobile. */
.about-hero {
  position: relative;
  min-height: 60vh;
  min-height: 60svh;
  padding: calc(var(--nav-h) + 120px) 0 100px;
  background: var(--color-cream);
  overflow: hidden;
}
.about-hero .container {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(32px, 5vw, 80px);
  align-items: center;
}
.about-hero-content {
  position: relative;
  z-index: 2;
  max-width: none;
}
.about-hero-img {
  position: relative;
  right: auto;
  top: auto;
  transform: none;
  width: 100%;
  max-width: 760px;
  justify-self: end;
  aspect-ratio: 4 / 3;
  background: var(--color-sand);
  overflow: hidden;
  border-radius: 2px;
  z-index: 1;
}
.about-hero-img img {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: center;
  background: var(--color-sand);
  /* Slow drifting ken-burns so the photograph isn't static. */
  animation: kenburns 12s ease-in-out infinite alternate both;
}
@media (prefers-reduced-motion: reduce) {
  .about-hero-img img { animation: none; transform: scale(1.04); }
}
.about-body {
  padding: var(--pad-normal) 0;
  background: var(--color-cream);
}
.about-body .container { max-width: 780px; }
.about-body h2 {
  font-family: var(--font-display);
  font-size: clamp(32px, 4.5vw, 56px);
  line-height: 1.05;
  letter-spacing: -0.015em;
  margin: 72px 0 24px;
  max-width: 20ch;
}
.about-body h2:first-child { margin-top: 0; }
.about-body h2 em { font-style: italic; color: var(--color-havtorn); }
.about-body p {
  font-size: clamp(17px, 1.4vw, 19px);
  line-height: 1.65;
  color: var(--color-charcoal);
  margin-bottom: 24px;
  max-width: 60ch;
}
.about-body p.muted { color: var(--color-text-muted); }
.about-credits {
  margin-top: 96px;
  padding-top: 48px;
  border-top: 1px solid var(--color-sand);
}
/* Quiet hand-off link at the very bottom of /om-oss. The site lives
   inside upnorth.ax so visitors who arrive here directly need a path
   home; the link is small on purpose, not a CTA button. */
.about-back {
  margin-top: 64px;
  padding-top: 40px;
  border-top: 1px solid var(--color-sand);
  font-size: 14px;
  letter-spacing: 0.02em;
  color: var(--color-text-muted);
}
.about-back .link-underline { color: var(--color-charcoal); gap: 8px; }
.about-credits-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 40px;
}
.about-credit-col h4 {
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  margin-bottom: 14px;
  font-weight: 500;
}
.about-credit-col p {
  font-family: var(--font-display);
  font-style: italic;
  font-size: 20px;
  color: var(--color-charcoal);
  line-height: 1.4;
  margin: 0;
  max-width: none;
}

/* ── FINAL CTA (now: navigational, not commercial) ─────────────────── */
.final-cta {
  padding: var(--pad-breathe) 0;
  background: var(--color-evening);
  color: var(--color-cream);
  position: relative;
  overflow: hidden;
}
.final-cta::before {
  content: '';
  position: absolute;
  top: 0; left: 0;
  width: 1px;
  height: 40%;
  background: var(--color-havtorn);
}
.final-cta .container {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 48px;
  align-items: end;
}
.final-cta-h2 {
  font-family: var(--font-display);
  font-size: clamp(40px, 7vw, 96px);
  line-height: 1;
  letter-spacing: -0.02em;
  max-width: 14ch;
}
.final-cta-h2 em { color: var(--color-havtorn); font-style: italic; }
.final-cta-links { display: flex; gap: 12px; flex-wrap: wrap; }

/* ── FOOTER ────────────────────────────────────────────────────────── */
footer {
  background: var(--color-charcoal);
  padding: 72px 0 40px;
  color: rgba(250,247,242,0.7);
}
.footer-grid {
  display: grid;
  grid-template-columns: 1.3fr 1fr 1fr 1fr;
  gap: 48px;
  margin-bottom: 72px;
}
.footer-logo {
  font-family: var(--font-display);
  font-size: 32px;
  color: var(--color-warm-white);
  margin-bottom: 16px;
}
.footer-tagline {
  font-family: var(--font-display);
  font-style: italic;
  font-size: 16px;
  color: rgba(245,240,232,0.55);
  line-height: 1.45;
}
.footer-col h4 {
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-warm-white);
  font-weight: 500;
  margin-bottom: 16px;
}
.footer-col ul li { margin-bottom: 10px; font-size: 14px; }
.footer-col ul a { color: rgba(250,247,242,0.6); transition: color 220ms var(--ease-out-expo); }
.footer-col ul a:hover { color: var(--color-havtorn); }
.footer-bottom {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-top: 32px;
  border-top: 1px solid rgba(250,247,242,0.08);
  font-size: 12px;
  color: rgba(250,247,242,0.4);
  flex-wrap: wrap;
  gap: 16px;
}
.footer-bottom a { color: rgba(250,247,242,0.6); border-bottom: 1px solid rgba(250,247,242,0.2); padding-bottom: 1px; }
.footer-bottom a:hover { color: var(--color-havtorn); border-bottom-color: var(--color-havtorn); }

/* ── RESPONSIVE ────────────────────────────────────────────────────── */
@media (max-width: 960px) {
  .portal-grid { grid-template-columns: 1fr; }
  .portal-1, .portal-2, .portal-3, .portal-4 { grid-column: span 1; aspect-ratio: 4 / 5; }
  .portal-arrow { width: 100%; justify-content: center; }
  .portals-head, .flavours-head { grid-template-columns: 1fr; gap: 24px; }
  /* Flavour cards stack vertically: image full-width on top, text block
     below. The previous 140px side-image layout broke on the middle
     card because "Blåbär & Citronmeliss" wraps and forces the grid row
     taller than 140px, stretching the image and colliding with copy. */
  .flavours-grid { grid-template-columns: 1fr; gap: 20px; }
  .flavour-card { display: block; }
  /* The previous 16:10 wrapper + cover was cropping the top and bottom
     of the cans on mobile. Switch to a portrait-friendly ratio with
     contain so the full can renders against the card background. */
  .flavour-card-imgwrap { aspect-ratio: 4 / 5; width: 100%; background: rgba(30,30,26,0.04); }
  .flavour-card-imgwrap img { object-fit: contain; }
  .flavour-card-body { padding: 20px 22px 26px; }
  .flavour-card-stripe { display: block; height: 2px; }
  .ing-track { height: 280vh; }
  .ing-layout { grid-template-columns: 1fr; gap: 32px; }
  .product-box { justify-self: center; max-width: 320px; }
  .pour .container { grid-template-columns: 1fr; gap: 32px; }
  .lifestyle-grid { grid-template-columns: 1fr; gap: 32px; }
  .final-cta .container { grid-template-columns: 1fr; gap: 32px; }
  .about-hero .container { grid-template-columns: 1fr; gap: 32px; }
  .about-hero-img { width: 100%; max-width: none; aspect-ratio: 4 / 3; order: 2; }
  .about-hero-content { order: 1; }
  .about-credits-grid { grid-template-columns: 1fr; gap: 24px; }
  .footer-grid { grid-template-columns: 1fr 1fr; gap: 32px; }
  .nav-links { display: none; }
  .hamburger { display: flex; }
  .showcase-caption-text { font-size: clamp(30px, 8vw, 48px); }
}
@media (max-width: 560px) {
  .hero { padding-top: 100px; padding-bottom: 60px; }
  .hero-h1 { font-size: clamp(44px, 12vw, 72px); }
  .footer-grid { grid-template-columns: 1fr; }
  .marquee-strip { font-size: 28px; }
}

/* ─────────────────────────────────────────────────────────────────
   MOBILE POLISH PASS  (≤720px)
   Targeted tightening of paddings, headlines and components that were
   sized for desktop. Kept in one block so it's easy to audit.
   ───────────────────────────────────────────────────────────────── */
@media (max-width: 720px) {
  :root {
    /* Vertical rhythm tightens on small screens — the desktop clamps
       collapsed to ~72px which still feels too generous against a
       narrow viewport. */
    --pad-tight:   48px;
    --pad-normal:  64px;
    --pad-breathe: 96px;
  }
  .container,
  .container-narrow { padding: 0 20px; }

  /* Nav: smaller logo, tighter right rail */
  .nav-logo { font-size: 18px; }
  .nav-right { gap: 10px; }

  /* Concept ribbon: keep on a single line, shrink type */
  .concept-ribbon { font-size: 10.5px; padding: 7px 16px; }

  /* Mobile header on subpages (drycken / ingredienser / filosofi /
     om-oss — anything with body.theme-light): force the dark
     cream-on-charcoal scheme from the very first paint, before any
     scroll. The default cream-text-on-cream-bg was making the logo,
     hamburger and links invisible until the user scrolled enough to
     trigger nav-scrolled. Home page (no theme-light class) keeps the
     cream-on-dark hero treatment. */
  body.theme-light .nav,
  body.theme-light.nav-scrolled .nav { background: rgba(245,240,232,0.86); backdrop-filter: blur(20px) saturate(160%); -webkit-backdrop-filter: blur(20px) saturate(160%); }
  body.theme-light .nav .nav-logo,
  body.theme-light .nav .nav-links a,
  body.theme-light .nav .lang-btn { color: var(--color-charcoal) !important; }
  body.theme-light .nav .hamburger span { background: var(--color-charcoal) !important; }
  body.theme-light .nav .lang-sep { background: var(--color-sand) !important; }
  /* Concept ribbon stays its own ink colour on subpages too — its dark
     bar above the nav reads fine on either theme. */

  /* When the nav probe lands on a dark section while we're already
     forced light (rare on mobile subpages but possible on filosofi
     hero), keep nav cream so it's visible against the dark band. */
  body.theme-light.nav-on-dark .nav { background: rgba(15,15,13,0.6); }
  body.theme-light.nav-on-dark .nav .nav-logo,
  body.theme-light.nav-on-dark .nav .nav-links a,
  body.theme-light.nav-on-dark .nav .lang-btn { color: var(--color-warm-white) !important; }
  body.theme-light.nav-on-dark .nav .hamburger span { background: var(--color-warm-white) !important; }

  /* Mobile menu credit / "Concept av" line — was 12-13px on desktop and
     felt oversized below the 44px menu links. Tighten letter-spacing
     and reduce the uppercase label size. */
  .mobile-menu-credit { font-size: 11px; letter-spacing: 0.12em; gap: 6px; }
  .mobile-menu-credit strong { font-size: 12px; }

  /* Page-hero (drycken, ingredienser, om-oss): trim top space so the
     headline isn't pushed below the fold by the nav + ribbon combo. */
  .page-hero { padding: calc(var(--nav-h) + 64px) 0 56px; }
  .page-hero-h1 { font-size: clamp(40px, 11vw, 64px); }
  .page-hero-sub { font-size: 15px; }

  /* About hero — smaller padding, tighter headline */
  .about-hero { padding: calc(var(--nav-h) + 56px) 0 64px; min-height: 0; }

  /* Display headings across sections */
  .display-md { font-size: clamp(34px, 9vw, 48px); }
  .manifesto-quote { font-size: clamp(28px, 8vw, 38px); }
  .lifestyle-h2,
  .pour-h2,
  .final-cta-h2 { font-size: clamp(30px, 8.5vw, 44px); }

  /* Showcase: contain on mobile means a lot of empty letterboxing —
     switch back to cover with a top-anchor so the can stays visible.
     Use dvh (dynamic viewport) so the sticky panel always matches the
     current viewport: 100svh stayed locked to the smallest possible
     viewport, which left a black bar at the bottom whenever iOS Safari
     collapsed its URL bar — the bug the user described where a strip
     under the video only disappeared at "4 / 4". */
  .showcase-video { object-fit: cover; object-position: center 35%; }
  .showcase-sticky {
    height: calc(var(--showcase-vh, 100dvh) + 2px);
    min-height: calc(100dvh + 2px);
  }

  /* Pour video block: smaller stack gap */
  .pour .container { gap: 24px; }

  /* Manifesto: meta line wraps better with smaller font */
  .manifesto-meta { font-size: 13px; flex-wrap: wrap; gap: 6px 12px; justify-content: center; }

  /* Flavour preview: keep the wrapper a bit taller than wide so the
     full can sits inside without being cropped top/bottom. The previous
     1:1 wrapper + object-fit:cover was chopping the top and bottom of
     the can imagery. Switch to contain so the entire can is visible
     against the cream background. */
  .flavour-preview-imgwrap { aspect-ratio: 3 / 4; }
  .flavour-preview-imgwrap img { object-fit: contain; transform: scale(1) !important; }

  /* ── MOBILE PERFORMANCE PASS ──
     Kill always-running infinite animations on small screens. These
     keep the compositor and decoders busy for the entire session and
     were the main cause of scroll jank on mid-range phones. Entry
     animations (reveal / fade-up) are untouched. */
  .hero-video.hero-still,
  .ing-intro-still,
  .flavour-card-imgwrap img,
  .ing-intro-video,
  .lifestyle-video { animation: none !important; }
  /* Film grain overlay is purely decorative — skip on mobile. */
  .grain, .grain--subtle { display: none; }
  /* Ken-burns on the about hero image — also kill. */
  .about-hero-img img { animation: none !important; transform: scale(1.04); }

  /* Marquee inside .portals shouldn't dominate the viewport */
  .marquee-strip { padding: 22px 0; font-size: 24px; }
  .marquee-strip .dot { margin: 0 14px; }

  /* Final CTA: stack buttons full width */
  .final-cta-links { flex-direction: column; align-items: stretch; }
  .final-cta-links .btn { justify-content: center; }

  /* Footer: tighten gaps */
  .footer-grid { gap: 32px 16px; }
  .footer-tagline { font-size: 13px; }

  /* Kill horizontal overflow risks from any rogue transforms.
     IMPORTANT: `overflow-x: hidden` on <body> silently breaks
     `position: sticky` on all descendants (the drycken showcase and
     ingredients scrollytelling depend on it). `overflow-x: clip` gives
     the same visual result without creating a new scroll container. */
  html, body { overflow-x: clip; }
}

@media (max-width: 420px) {
  .hero-eyebrow { font-size: 10.5px; }
  .hero-sub { font-size: 14px; }
  .marquee-strip { font-size: 20px; }
  .marquee-strip .dot { margin: 0 10px; }
  .page-hero-h1 { font-size: clamp(34px, 12vw, 56px); }
  .display-md { font-size: clamp(30px, 10vw, 42px); }
}

/* -- PAGE TRANSITION FADE -----------------------------------------
   Soft cross-fade between pages. Body opacity fades to 0 on link click
   (no dark veil overlay — the user found the solid-black version too
   harsh). The destination page comes in via the natural opacity:1
   default. Quick enough to feel like a single visual breath, slow
   enough that the nav doesn't strobe. */
html body { opacity: 1; transition: opacity 280ms var(--ease-out-expo); }
html.page-fade-in body { opacity: 0.001; }
html.page-fade-in.page-ready body { opacity: 1; }
html.page-fade-out body { opacity: 0; }
@media (prefers-reduced-motion: reduce) {
  html body { transition: none !important; opacity: 1 !important; }
}

/* -- PAGE LOADER -------------------------------------------------
   Brief ink-coloured veil with the wordmark. Injected by JS once on
   first paint, kept on screen for ~500ms, then faded out. Reused as
   the cover during page-to-page navigations so the destination
   never appears mid-paint. */
.page-loader {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: var(--color-ink);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 18px;
  pointer-events: auto;
  transition: opacity 420ms var(--ease-out-expo), visibility 0s linear 420ms;
}
.page-loader.is-hidden { opacity: 0; visibility: hidden; pointer-events: none; }
.page-loader.is-active { opacity: 1; visibility: visible; transition: opacity 220ms var(--ease-out-expo); }
/* Synchronous head script in each page sets html.no-loader if the
   session has already shown the veil once. We then kill the loader
   pre-paint so subsequent navigations never flash it. */
html.no-loader .page-loader { display: none !important; }
.page-loader-mark {
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(34px, 6vw, 56px);
  letter-spacing: -0.02em;
  color: var(--color-warm-white);
  position: relative;
  padding-right: 14px;
}
.page-loader-mark::after {
  content: '';
  position: absolute;
  right: 0; top: 14%;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--color-havtorn);
  animation: loader-pulse 1.2s ease-in-out infinite;
}
.page-loader-bar {
  width: 120px; height: 1px;
  background: rgba(245,240,232,0.18);
  position: relative;
  overflow: hidden;
}
.page-loader-bar::after {
  content: '';
  position: absolute; top: 0; left: -40%;
  width: 40%; height: 100%;
  background: var(--color-havtorn);
  animation: loader-sweep 1.1s cubic-bezier(.65,0,.35,1) infinite;
}
@keyframes loader-pulse {
  0%, 100% { transform: scale(1);   opacity: 1; }
  50%      { transform: scale(0.7); opacity: 0.55; }
}
@keyframes loader-sweep {
  0%   { left: -40%; }
  100% { left: 100%; }
}
@media (prefers-reduced-motion: reduce) {
  .page-loader-mark::after,
  .page-loader-bar::after { animation: none; }
}
