/* Mat — delikatessesiden. Kun det sidespesifikke: 3D-disken.
   Resten av siden bruker assets/site.css som før. */

/* Kapitteltitlene (.j-title, gjenbrukt fra v2.css) — samme headerfont/
   -stil som resten av siten, kopiert hit i stedet for hele v2-body-
   klassen (som /mat aldri har hatt, se historikk i git — den drar med
   mørk body-bakgrunn og en kornoverlay-animasjon som ikke hører hjemme
   her). --font-mega er global Gaglio Bold nå (tokens.css), trenger
   ingen lokal overstyring lenger. Alle Gaglio-vekter lastes sentralt. */
.j-mega, .j-title { font-weight: 400; }
.j-title { font-family: "Gaglio-Medium", var(--font-mega); }
.j-title .script { font-family: "Gaglio-Medium", var(--font-mega); }

/* (Ingen egen Swarsh Daisy-import her lenger: sitatstilen er definert
   sentralt i tokens.css — --font-quote/--font-quote-italic — som også
   eier @font-face-importene. Se .disk-black-lead.) */

/* .site-header sin vanlige position:sticky brytes av GSAP sin pin-spacer
   (disk-scene-hero pinnes av disk3d.js) — samme fiks som /v2 og /om
   allerede bruker for sine pinnede reiser (.v2-body .site-header i
   v2.css): tving fixed så headeren alltid blir stående, uansett hva
   pin-spaceren gjør med resten av dokumentflyten. */
.site-header {
  position: fixed;
  left: 0; right: 0;
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border-bottom-color: transparent;
}

/* Fallback mot den lyse veggen mens 3D-heroen er pinnet (disk3d.js
   setter/fjerner klassen — se den utførlige begrunnelsen der).
   mix-blend-mode: difference (site.css) blander normalt menyteksten mot
   det som faktisk ligger bak, men her ligger WebGL-canvasen inni en
   GSAP-transformert (pinnet) seksjon — en transform på en stamfar
   ISOLERER stacking-konteksten, så teksten differensierer mot en flat
   bakgrunnsfarge i sin egen kontekst i stedet for de faktiske canvas-
   pikslene. Resultatet var fast hvit tekst uten reell kontrast-effekt.
   !important trengs for å slå de generelle site.css-reglene (også
   !important, se der) — veggen her er PÅLITELIG lys, så en fast mørk
   farge er riktigere enn et blend-mode-triks som likevel ikke virker. */
.site-header.mat-hero-header .site-nav a::before,
.site-header.mat-hero-header .site-nav a::after,
.site-header.mat-hero-header .account-link,
.site-header.mat-hero-header .logout-link,
.site-header.mat-hero-header #lang-switch button {
  mix-blend-mode: normal !important;
  color: var(--ink) !important;
}
.site-header.mat-hero-header .site-nav a.is-active::before,
.site-header.mat-hero-header .site-nav a.is-active::after {
  color: var(--red) !important;
}
/* .nav-toggle sine tre streker er BAKGRUNNSFARGEN på et tomt element
   (ikke tekst), så «color» over gjør ingenting for dem — egen regel. */
.site-header.mat-hero-header .nav-toggle span {
  mix-blend-mode: normal !important;
  background: var(--ink) !important;
}

/* Full bredde på desktop. På mobil er scenen bredere enn skjermen og
   ligger i en horisontal scroller — venstrestilt start, sveip for å se
   resten av disken. */
.disk-scene {
  /* Matcher scene.background i disk3d.js (kveldsvarm, dempet vegg) —
     endres de, endres begge. */
  background: #dcc9a4;
}
.disk-scroll {
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none; /* scenen ER innholdet; stripa under skjemmer */
}
.disk-scroll::-webkit-scrollbar { display: none; }
/* Sideveis sveip er LÅST til den pinnede vertikal-tilten er scrollet
   ferdig (disk3d.js sin heroTrigger, onLeave-callback) — pan-y lar
   ethvert drag her passere videre som vanlig SIDE-scroll i stedet for
   å bli tolket som en horisontal sveip på canvasen. Uten denne fanget
   siden en sideveis gest allerede på aller første skjermbilde, før
   brukeren i det hele tatt hadde begynt å scrolle nedover — det slo
   ut av rytmen resten av siden bygger på (vertikal scroll driver alt
   først, sideveis bevegelse kommer som en konsekvens av den, aldri
   som en konkurrerende gest fra start). Åpnes permanent («auto», som
   gir elementet tilbake sin naturlige evne til å konsumere horisontale
   drag som scrollLeft) idet man har scrollet forbi tilten én gang. */
@media (max-width: 900px) {
  .disk-scroll { touch-action: pan-y; }
  .disk-scroll.is-swipe-unlocked { touch-action: auto; }
}
.disk-stage {
  position: relative;
  width: 100%;
  /* Gulv på scenens fysiske bredde: blir vinduet smalere enn dette,
     krymper ikke 3D-oppstillingen videre — .disk-scroll gir sideveis
     scroll i stedet (samme oppførsel som mobil). */
  min-width: 1100px;
  height: clamp(420px, 72vh, 760px);
}
.disk-stage canvas { display: block; width: 100%; height: 100%; }
@media (max-width: 900px) {
  .disk-stage { width: 220vw; min-width: 0; } /* sentreres av disk3d.js, sveip begge veier */
}

/* Mobil-tittelen (DOM-lag, se index.html) og sveipe-vakta: begge finnes
   kun under 901px — desktop har 3D-tittelen på veggen og ingen sveiping. */
.disk-hero-title { display: none; }
.disk-swipe-guard { display: none; }
@media (max-width: 900px) {
  .disk-hero-title {
    display: block;
    position: absolute;
    left: 16px;
    right: 16px;
    /* Samme høyde som 3D-tittelen sto i — rammen (fit() i disk3d.js)
       reserverer fortsatt denne luften over Patricks hode. */
    top: clamp(110px, 22svh, 230px);
    z-index: 5; /* over canvas, under den sorte shapen (30) og header (40) */
    text-align: center;
    pointer-events: none;
  }
  .disk-hero-kicker {
    margin: 0 0 16px;
    font-family: var(--font-nav);
    font-weight: 400;
    font-size: 0.82rem;
    letter-spacing: 0.34em;
    text-transform: none;
    color: rgba(3, 68, 51, 0.62);
  }
  .disk-hero-line {
    margin: 0;
    font-family: var(--font-title); /* Gaglio Bold — samme som titlene på / */
    font-weight: 400;
    font-size: clamp(2.5rem, 13.4vw, 3.8rem);
    line-height: 1.04;
  }
  .disk-hero-line1 { color: var(--ink); }
  .disk-hero-line2 { color: var(--red); }
  .disk-swipe-guard {
    display: block;
    position: absolute;
    inset: 0 0 auto 0;
    /* Ned til like over disken/maten i startvisningen — alt over dette
       feltet kan ikke starte en sideveis-sveip. */
    height: 55%;
    z-index: 4;
    /* pan-y: vertikale drag slipper gjennom til sidescrollen (native
       kjede opp til dokumentet), horisontale drag har ingen mottaker
       her og dør — .disk-scroll under får aldri touch-en. */
    touch-action: pan-y;
  }
}

/* ---------- Hero-varianten: full-bleed 3D øverst på siden ----------
   Erstatter den tidligere bilde-heroen (.vista) — ingen tittel/knapper
   oppå, bare disken. Fyller hele viewporten, også bak den transparente/
   blendede headeren — negativ margin trekker seksjonen opp under
   headeren (som selv tegnes oppå, fixed). Beige (.disk-scene sin
   bakgrunn) og sideveggene fyller dermed hele høyden fra aller øverst,
   ingen egen tekst-header foran som brøt opp fargen/gjorde scenen
   mindre. */
.disk-scene-hero {
  position: relative;
  isolation: isolate;
  height: 100svh;
  min-height: 580px;
  margin-top: calc(-1 * var(--header-h, 143px));
  overflow: hidden;
}
/* Mobil: INGEN negativ margin — headeren er position:fixed (tar null
   plass i flyten), så heroen starter uansett på dokument-topp 0. Den
   negative marginen skjøv bare heroens øverste ~96px UT av dokumentet
   (over scroll 0): pin-triggeren ("top top" i disk3d.js) målte da
   starten til -96px, en scrollposisjon som ikke finnes, og tilten fikk
   et GULV på ~12 % — scenen kom aldri helt tilbake til utgangspunktet
   når man scrollet opp igjen. (Må stå ETTER grunnregelen over — samme
   spesifisitet, kaskaden avgjør.) */
@media (max-width: 900px) {
  .disk-scene-hero { margin-top: 0; }
}
.disk-scene-hero .disk-scroll,
.disk-scene-hero .disk-stage {
  height: 100%;
}
/* Ikke noe CSS-tak på canvasbredden: den skal alltid gå helt ut til
   skjermkantene (en kappet canvas ved siden av flat CSS-beige ga en
   synlig søm — 3D-veggen er lyssatt/vignettert, ikke én flat farge).
   2350px-taket på selve OPPSTILLINGEN ligger i stedet i kameraet
   (fit() i disk3d.js): på bredere skjermer holder modellene samme
   størrelse som ved 2350, og man ser bare mer vegg på sidene. */
/* Bunnen av rammen skal fade mot samme sort som diskens underside der
   nede — IKKE den grønne merkefargen (leste som feil/utenforstående
   farge mot en ellers varm, lys/sort scene). Fallback for mobil/
   reduced-motion; på desktop tar den rullende shapen (.disk-bottom-fade,
   synlig fra start) over rollen, og disk3d.js setter .has-roll. */
.disk-scene-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(to top, rgba(10, 10, 10, 0.7) 0%, rgba(10, 10, 10, 0.32) 22%, transparent 48%);
  pointer-events: none;
}
/* Denne gradienten ble tidligere skjult når den rullende shapen tok
   over (.has-roll). Etter at oppstillingen dyttes ned (linseforskyvning
   i disk3d.js) ligger diskens bunnkant UNDER skjermkanten ved start, og
   shapen — som ankres i den kanten — er da utenfor bildet: uten denne
   sto bunnen helt uten sort. Den blir liggende som base, og den solide
   shapen legger seg oppå når disken tilter opp. */

/* Bunnkant-shapen: en solid sort flate med feather-kant øverst.
   disk3d.js projiserer diskens EKTE fremre bunnkant (3D-punkt) til
   skjermkoordinater hver frame og setter translateY i piksler direkte
   — feather-kanten treffer dermed alltid der disken faktisk er sort,
   uansett oppløsning/aspekt/tilt (ikke gjettede scroll-prosenter).
   Fortsetter opp og ut når fullskjermbildet (sort topp) tar over.
   translateY(100%) er kun startverdien før JS har målt noe — helt
   under skjermkanten, ingen synlig flash. position:fixed (se
   index.html for hvorfor den ligger UTENFOR .disk-scene-hero). */
.disk-bottom-fade {
  position: fixed;
  left: 0; right: 0;
  /* FAST høyde + transform/clip-path fra disk3d.js hver frame — IKKE
     top/height: de utløser layout, og per-frame-skriving ga målbar
     hakking akkurat i overgangen mot fullskjermbildet. translateY
     ankrer toppen (feather-kanten) på diskens projiserte bunnkant, og
     clip-path kutter bunnen ved bildets toppkant — begge er rene
     kompositor-operasjoner. Startverdien translateY(100%) = hele
     elementet under skjermen til JS har målt (ingen flash). */
  top: 0;
  height: 160svh;
  transform: translateY(100%);
  will-change: transform;
  /* Under .site-header (z 40, se site.css) — shapen skal ligge over
     innholdet, aldri over menyen. */
  z-index: 30;
  /* Feather i PIKSLER, ikke prosent: med prosent flyttet den solide
     kanten seg med elementhøyden, og toppen av shapen var i praksis
     gjennomsiktig langt nedover — det var derfor det sto en beige
     stripe mellom disk og shape. */
  background: linear-gradient(to bottom, rgba(10, 10, 10, 0) 0px, #0a0a0a 140px);
  pointer-events: none;
}

/* Teksten oppå det sorte feltet under disken. Fixed av samme grunn som
   .disk-bottom-fade (utenfor pin-transformen, se index.html), og med
   opacity styrt av disk3d.js: inn med tilten, ut når bildet tar over.
   Vises kun når den rullende shapen faktisk kjører (has-roll) — på
   mobil/reduced-motion finnes ikke det sorte feltet den skal ligge på.
   Plassert på 62 % ned, ikke midten: øvre halvdel er fortsatt disk ved
   midt-tilt, teksten skal ligge trygt i det sorte. */
.disk-black-copy {
  display: none;
  position: fixed;
  /* Venstrejustert, ca. 30% inn fra venstre kant (var 40 % — ga en for
     smal, høy spalte; se data-scroll-reveal="left" i index.html for selve
     tekstjusteringen). */
  left: 30%;
  top: 62%;
  transform: translate(0, -50%);
  z-index: 31; /* over .disk-bottom-fade (30), under .site-header (40) */
  text-align: left;
  opacity: 0;
  pointer-events: none;
  /* Eget kompositor-lag: opacity OG transform (medscrollingen) scrubbes
     hver frame fra disk3d.js — uten laget re-rastreres hele den store
     tekstflaten per frame (samme lag-symptom som sitatene på /om hadde). */
  will-change: opacity, transform;
}
/* Slås på fra disk3d.js (initScrollTilt) — en CSS-søskenselektor mot
   .has-roll virker ikke: GSAP-pinnen pakker heroen inn i en .pin-spacer,
   så de to er ikke lenger søsken i DOM-en. */
.disk-black-copy.is-on { display: block; }
.disk-black-copy .j-title { margin: 0; }
/* Ingressen i SITATSTILEN — den definerte stilen for tekst oppå bilder/
   mørke flater (--font-quote i tokens.css, samme som /om sine sitater):
   Swarsh Daisy, clamp(1.8rem, 4.9vw, 3.8rem), line-height 1.02. Samme
   formatering som .j-quote p i om.css — bare venstrestilt her (styrt av
   ScrollRevealText via data-scroll-reveal="left" i index.html). */
.disk-black-lead {
  /* Boksen starter på 30vw (.disk-black-copy) — bredden må holde seg
     innenfor resten av viewporten med litt luft til høyre kant. */
  max-width: min(62vw, 980px);
  margin: 26px 0 0;
  font-family: var(--font-quote);
  font-weight: 400;
  /* Også begrenset av høyden: boksen er fast plassert, så på lave
     skjermer ville en høy tekstblokk gått utenfor topp/bunn. */
  font-size: clamp(1.6rem, min(4.9vw, 6.6vh), 3.8rem);
  line-height: 1.02;
  color: var(--on-dark);
  /* Ingen text-shadow her — på helsort bakgrunn er den usynlig, men
     raster-kostnaden var høyst reell: en blurret skygge over en så stor
     glyf-flate repaintes for hver opacity-frame, som var nøyaktig
     symptomet som gjorde /om treg i sin tid. */
}
.disk-black-lead em {
  font-family: var(--font-quote-italic);
  font-style: normal; /* kursiven er bakt inn i fonten, se tokens.css */
}
/* Mobil: hele boksen venstrestilles fra sidekanten (gutteren) i stedet
   for å starte 40 % inn — 40 %-innrykket ga en smal, høyreklemt spalte
   på en 375px-skjerm. */
@media (max-width: 900px) {
  .disk-black-copy { left: var(--gutter, 22px); right: var(--gutter, 22px); }
  .disk-black-lead { max-width: none; }
}
.disk-black-ingress {
  margin: 20px 0 0;
  font-family: var(--font-nav);
  font-size: 0.85rem;
  letter-spacing: 0.18em;
  text-transform: none;
  color: var(--on-dark-soft);
}

/* Fullskjermbildet rett etter 3D-heroen: toppen er sort og fader ned i
   selve bildet — når pinnen slipper og denne glir inn, er den sort-mot-
   sort med .disk-bottom-fade, og disk3d.js scrubber overlayen ut i takt
   med at seksjonen tar over. Innholdet fortsetter under. */
.mat-fullimg {
  position: relative;
  height: 100svh;
  overflow: hidden;
  background: #0a0a0a;
}
.mat-fullimg img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  /* Overskala + parallax settes samlet av disk3d.js (GSAP eier hele
     transformen — en CSS-scale her ville blitt overskrevet av tweenen). */
  will-change: transform;
}
/* Ingen topp-gradient: møtet med den sorte shapen over skal være en
   HARD kant — bildet parallakserer inn mot det sorte, ikke fades. */

/* Teksten oppå seksjonen — sentrert, ligger over hele forløpet (sort
   flate → bilde), samme .j-word-stil som pusterom-ordene lenger ned.
   Absolutt (ikke flex) så den ikke konkurrerer med bildet om
   flex-radplass — bildet fyller seksjonen for seg selv (posisjonert
   absolutt over), teksten sentreres oppå uavhengig. Svak mørk tint bak
   (::before) sikrer lesbarhet også der bildet selv er lyst, uten å
   bryte den harde sorte kanten over. */
.mat-fullimg::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: rgba(10, 10, 10, 0.32);
  pointer-events: none;
}
.mat-fullimg .j-word {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 2;
  text-align: center;
}

/* Sitatmodulen (band, site.css) er en 56vh-stripe i utgangspunktet —
   klemt mellom to fullskjermsmoduler her leste den som et smalt bånd
   som brøt rytmen. På denne siden får den full høyde som alt annet. */
.band { height: 100svh; }

/* ---------- Bildehjulet ----------
   Kortene legges i ring med transform: rotate(θ) translateY(-r), og
   selve ringen roteres av disk3d.js mens man scroller forbi. Radien
   er en egenskap (--r) så den kan krympes på mobil uten å røre
   vinkelutregningen. Teksten står i ro i midten. */
.mat-wheel {
  position: relative;
  /* 1.5× viewporthøyden (var 100svh): mer scrolldistanse gjennom
     seksjonen — hjulet får rotere lenger, og klokka/tittelen står
     luftigere mellom nabo-modulene. Gjelder desktop OG mobil. */
  min-height: 150svh;
  display: grid;
  place-items: center;
  overflow: hidden;
  background: var(--cream, #f3ead9);
  padding: clamp(60px, 10vh, 120px) var(--gutter);
}
.mat-wheel-ring {
  /* 20 % større enn den opprinnelige clamp(230px,32vw,430px). */
  --r: clamp(276px, 38vw, 516px);
  /* Fartsdrevet ring-utvidelse: 1 i hvile, opp mot ~1.6 rett etter et
     raskt scroll-drag — disk3d.js lerper denne mot et mål utledet av
     ScrollTrigger sin egen scroll-hastighet (self.getVelocity()) hver
     frame, og senker den sakte tilbake mot 1 når farten avtar. Egen
     variabel, ikke bakt inn i --r selv: --r er en ren layout-verdi
     (endres bare på media queries), mens denne er en løpende
     animasjonstilstand — å blande dem ville gjort begge vanskeligere
     å resonnere om hver for seg. */
  --r-scale: 1;
  /* Kortbredden som variabel: 3D-kortene ganger den (se
     .mat-wheel-card-3d) i stedet for å gjenta clamp-en med egne tall,
     som ville måttet holdes i synk manuelt gjennom hver media query. */
  --card-w: clamp(96px, 12vw, 168px);
  /* Fallback for rotasjonsvinkelen MÅ stå her, ikke på kortet: en
     deklarasjon på kortet selv vinner over arven herfra, så kortene
     ble stående på 0 og motrotasjonen uteble. disk3d.js overskriver
     denne per frame. */
  --spin: 0deg;
  position: absolute;
  inset: 0;
  margin: auto;
  width: 0;
  height: 0;
  will-change: transform;
  /* Ringen selv er et 0×0-punkt i midten og skal aldri fange peker —
     men pointer-events ARVES, så kortene må ta den tilbake eksplisitt
     (se .mat-wheel-card) ellers er hele hjulet dødt for klikk og hover. */
  pointer-events: none;
}
.mat-wheel-card {
  position: absolute;
  margin: 0;
  /* Tar tilbake pekerhendelsene ringen slår av: kortene er det eneste
     som SKAL være klikkbart (wheel-modal.js) og hover-bart (wheel3d.js). */
  pointer-events: auto;
  width: var(--card-w);
  aspect-ratio: 3 / 4;
  /* Kortet flyttes ut på radien og roteres tilbake til slutt, så motivet
     står rett opp mens PLASSERINGEN følger ringen. Motrotasjonen MÅ være
     siste ledd i denne kjeden — som egen `rotate`-egenskap anvendes den
     før `transform` og dreier hele utstikket i stedet for bare motivet,
     som forvrengte ringen til en spiral. --spin settes på ringen av
     disk3d.js (fallback på ringen) og arves hit. */
  transform:
    translate(-50%, -50%)
    rotate(var(--a))
    translateY(calc(-1 * var(--r) * var(--r-scale)))
    rotate(calc(-1 * (var(--a) + var(--spin))));
  box-shadow: 0 18px 40px rgba(3, 68, 51, 0.22);
  background: var(--paper);
  padding: 6px;
}
.mat-wheel-card img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* De 3D-kortene (wheel3d.js) — INGEN ramme, i motsetning til fotokortene:
   objektet skal se ut som det svever fritt i ringen, ikke ligge i en
   hvit plakatkant. Nullstiller alt fotokort-rammen (.mat-wheel-card)
   ellers gir (hvit bunn, padding, skygge) — canvasen er transparent
   (alpha:true i wheel3d.js), så veggen bak skinner gjennom direkte. */
.mat-wheel-card-3d {
  background: none;
  padding: 0;
  box-shadow: none;
  /* Dobbelt så stort som fotokortene — og det er SELVE KORTET (og
     dermed canvasen) som dobles, ikke en transform: scale() på et lite
     kort. Skalering ville forstørret en canvas rendret i liten
     oppløsning og gitt uskarpe kanter; her får rendereren beskjed om
     den nye størrelsen (ResizeObserver → fit() i wheel3d.js) og tegner
     skarpt i full oppløsning. At de dermed overlapper nabokortene er
     ønsket — objektene skal bryte ut av ringens rutenett. */
  width: calc(var(--card-w) * 2);
  z-index: 1; /* over fotokortene der de overlapper */
}
.mat-wheel-card-3d canvas { width: 100%; height: 100%; display: block; }

/* Urskiven i midten (disk3d.js sin buildClock() fyller den med SVG).
   Sentreres med samme inset/margin-triks som ringen. Ligger MELLOM
   kortene og tittelen i lagrekkefølgen: viserne sveiper synlig ut fra
   midten, men bak teksten, så tittelen aldri blir vanskelig å lese. */
.mat-clock {
  position: absolute;
  inset: 0;
  margin: auto;
  width: clamp(360px, 50vw, 820px);
  height: clamp(360px, 50vw, 820px);
  pointer-events: none;
}
.mat-clock svg { width: 100%; height: 100%; display: block; }
/* Alt tegnes med ÉN fysisk piksel uansett skjermstørrelse:
   vector-effect: non-scaling-stroke løsriver streken fra viewBox-
   skaleringen, så stroke-width: 1 betyr 1px på skjermen — ikke 1
   brukerenhet, som på en 800px-bred skive ville blitt en 4px tykk
   strek. Det er dette som holder skiva grafisk lett i alle størrelser. */
.mat-clock-face,
.mat-clock-tick,
.mat-clock-hand {
  vector-effect: non-scaling-stroke;
}
.mat-clock-face { fill: none; stroke: rgba(3, 68, 51, 0.14); stroke-width: 1; }
.mat-clock-tick { stroke: rgba(3, 68, 51, 0.28); stroke-width: 1; }
/* transform-origin i BRUKERENHETER (viewBox-koordinater), ikke prosent:
   prosent regnes mot elementets egen bbox — en viser-linje er nesten
   uten bredde, så 50% ville rotert den om sin egen strek i stedet for
   om urskivens midtpunkt. */
.mat-clock-hand {
  stroke-width: 1;
  stroke-linecap: butt; /* rene strekender, ingen avrundet «pølse» */
  transform-origin: 100px 100px;
}
.mat-clock-hand-hour { stroke: var(--ink); }
.mat-clock-hand-min { stroke: var(--red); }

.mat-wheel-title {
  position: relative;
  z-index: 2;
  margin: 0;
  text-align: center;
  font-family: var(--font-mega);
  font-weight: 700;
  /* Et hakk ned fra 5vw/4.4rem: teksten er lengre nå («alle døgnets
     tider»), og skal fortsatt holde seg innenfor urskiven bak. */
  font-size: clamp(1.7rem, 4.1vw, 3.7rem);
  line-height: 1.04;
  color: var(--ink);
}
.mat-wheel-title .script { color: var(--red); }
@media (max-width: 900px) {
  /* 20 % større enn clamp(160px,46vw,260px), samme prinsipp som
     grunnverdien over. */
  .mat-wheel-ring {
    --r: clamp(192px, 55vw, 312px);
    /* Bildene på hjulet: 15 % større enn grunnverdien
       (clamp(96px,12vw,168px)) — fungerte bra plassert der det nå
       ligger, men kortene selv var i minste laget på mobil. */
    --card-w: clamp(110px, 13.8vw, 193px);
  }
}
/* Bredere skjermer: karusellen får mer luft (høyere seksjon) og både
   radius og kortstørrelse skalerer videre i stedet for å flate ut ved
   430px/168px slik den gjorde før — på en ultrabred skjerm var hjulet
   fortsatt på "laptop-størrelse". */
@media (min-width: 1400px) {
  /* 1.5× av forrige 132vh. */
  .mat-wheel { min-height: 198vh; padding-block: clamp(90px, 15vh, 170px); }
  .mat-wheel-ring {
    /* 20 % større enn clamp(430px,27vw,620px). */
    --r: clamp(516px, 32vw, 744px);
    --card-w: clamp(168px, 13.5vw, 250px);
  }
}
@media (prefers-reduced-motion: reduce) {
  .mat-wheel-ring { will-change: auto; }
}

.band-quote cite {
  display: block;
  margin-top: 18px;
  font-style: normal;
  font-family: var(--font-nav);
  font-size: 0.8rem;
  letter-spacing: 0.16em;
  text-transform: none;
  color: var(--on-dark-soft);
}

/* ---------- Kapitlene (.j-chapter): bredere, to spalter, større bilder ----------
   Kun /mat — v2.css sine egne mål (44ch/460–640px) er urørt, gjelder
   fortsatt for / og /om. */
@media (min-width: 901px) {
  .j-viewport .j-panel { gap: clamp(48px, 6vw, 120px); }
  /* Midtstilt på skjermbredden: .j-panel har ingen justify-content i
     v2.css (default flex-start), så bilde + tekst la seg mot venstre
     kant med all luften samlet til høyre på brede skjermer. Innholdet
     har uansett et tak i bredden (bildebredde + .j-body max-width), så
     det er den ledige plassen som skal fordeles likt på hver side. */
  .j-viewport .j-chapter { justify-content: center; }
  /* max-height ved siden av bredden: uten den kunne et 40vw-bredt bilde
     (aspect-ratio 3/4 → opp mot 826px høyt) tvinge HELE panelet høyere
     enn viewporten på vanlige skjermer — da mister min-height:100svh +
     align-items:center sin sentrering all effekt, for boksen ER lenger
     enn viewporten. Med et hakk under 100svh i tak blir bildet aldri
     den delen som avgjør panelhøyden — raden (bilde + tekst) forblir
     kortere enn viewporten, og forblir dermed faktisk sentrert i den.
     object-fit: cover (v2.css) tar seg av at bildet fortsatt fyller
     boksen pent selv når høyden (ikke bredden) er det trange målet. */
  .j-viewport .j-media-tall { width: min(32vw, 480px); max-height: 68svh; }
  .j-viewport .j-media-big { width: min(34vw, 540px); max-height: 68svh; }
  .j-viewport .j-media-wide { width: min(38vw, 640px); max-height: 58svh; }
}
@media (min-width: 1200px) {
  /* To spalter: ren CSS multi-column, ingen ny markup nødvendig.
     column-span: all på tittelen holder den utenfor spaltene — den skal
     stå som en full-bredde overskrift over teksten, ikke brekke midt i. */
  .j-viewport .j-body {
    /* Dynamisk bredde: fyller det som er igjen ved siden av bildet
       (flex: 1 1 …), innenfor et gulv (min-width) og et tak (max-width)
       — ikke en fast bredde. Et EKSPLISITT min-width er også selve
       fiksen for et ellers usynlig problem: en flex-item med
       kolonnetekst (column-count) rapporterer sin egen, unaturlig store
       max-content-bredde til raden når min-width står på default
       («auto») — en kjent CSS-kvirk — og fikk hele panelet til å brekke
       om til to linjer (bilde over, tekst under) selv med god plass
       igjen, fordi .j-panel sin flex-wrap:wrap (v2.css) trigget på den
       innbilte bredden, ikke den faktiske. Et konkret tall her (ikke 0)
       både løser det OG setter et fornuftig gulv for lesbarheten i to
       spalter. */
    flex: 1 1 420px;
    min-width: 380px;
    max-width: 74ch;
    column-count: 2;
    column-gap: clamp(32px, 3vw, 56px);
  }
  .j-viewport .j-body .j-title {
    column-span: all;
    margin-bottom: 30px;
  }
  /* CTA-knappen (siste kapittel) skal ligge under begge spaltene, ikke
     havne fanget midt i kolonne to. */
  .j-viewport .j-body > .btn { column-span: all; margin-top: 8px; }
  /* Litt større og mer luftig på brede skjermer —「mer spennende」 uten
     å bryte den etablerte skalaen fra v2.css. */
  .j-viewport .j-title { font-size: clamp(2.6rem, 3.6vw, 4.8rem); }
  .j-viewport .j-num { font-size: clamp(4rem, 8vw, 7.5rem); }
}

/* ---------- Bildehjulets 3D-kort ---------- */
.mat-wheel-card-3d { cursor: grab; }
.mat-wheel-card-3d:active { cursor: grabbing; }

/* Klikkbare kort (wheel-modal.js) — synlig affordance uten å endre
   kortenes utseende i hvile. */
.mat-wheel-card { cursor: pointer; }
.mat-wheel-card:focus-visible { outline: 2px solid var(--ink); outline-offset: 4px; }

/* ---------- Storvisning (wheel-modal.js) ----------
   Panelet har bevisst overflow:visible: 3D-/bilde-sonen (.wheel-modal-
   media) stikker ut OVER selve panelkortet (negativ margin), som en
   plakat lagt oppå — ikke klippet av kortets egen avrundede kant. Selve
   scroll-lesbarheten (tittel/tekst) ligger i en egen, avrundet flate
   under, med sin egen overflow:hidden og indre smooth scroll. */
.wheel-modal {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: none;
  align-items: center;
  justify-content: center;
  padding: clamp(16px, 4vh, 60px) var(--gutter);
}
.wheel-modal.is-open { display: flex; }
.wheel-modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(1, 20, 15, 0.55);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
}
.wheel-modal-panel {
  position: relative;
  z-index: 1;
  width: min(92vw, 720px);
  max-height: min(88svh, 860px);
  display: flex;
  flex-direction: column;
  overflow: visible;
}
/* Lukkeknappen ligger i panelets øvre høyre hjørne. På desktop er det
   samtidig PAPIRETS hjørne: der er 3D-objektet absolutt posisjonert og
   ute av flyten, så papiret fyller panelet alene. På smal skjerm ligger
   media-sonen i flyten øverst, og krysset havner da i modalens øvre
   høyre hjørne, over objektsonen — mørk, uskarp bakgrunn gjør at det
   leses uansett hva som ligger bak. */
.wheel-modal-close {
  position: absolute;
  top: 14px;
  right: 14px;
  z-index: 6;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: none;
  background: rgba(1, 20, 15, 0.62);
  color: var(--paper);
  display: grid;
  place-items: center;
  cursor: pointer;
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  transition: background 0.2s ease, transform 0.2s ease;
}
.wheel-modal-close svg { width: 18px; height: 18px; }
.wheel-modal-close:hover { background: rgba(1, 20, 15, 0.88); transform: scale(1.06); }

/* 3D-/bilde-sonen — trekkes opp OVER scroll-kortet under med negativ
   bunnmarg, «ligger litt ut over kanten». */
.wheel-modal-media {
  position: relative;
  z-index: 2;
  /* Stablet layout (smal skjerm): moderat vekst. Doblingen hører til
     desktop-varianten lenger ned, der objektet ligger ved SIDEN av
     papiret — her ligger det oppå, og et dobbelt så stort objekt ville
     presset teksten ned i en 270px høy sprekk. */
  height: clamp(300px, 46vh, 520px);
  /* Hvor langt objektet bryter NED I papirkortet. Negativ clamp leses
     som vanlig (min ≤ preferert ≤ maks), bare med negative tall: dyp
     overlapp på høye skjermer, men aldri så dyp at den spiser tittelen
     på lave. Toppolstringen i .wheel-modal-body må følge denne. */
  margin-bottom: clamp(-120px, -10vh, -74px);
  display: grid;
  place-items: center;
  pointer-events: none; /* selve zonen — canvas under setter sin egen pointer-events */
}
.wheel-modal-media canvas {
  width: 100%;
  height: 100%;
  pointer-events: auto;
  touch-action: none; /* dra-for-å-rotere eier gesten, ikke siden sin scroll */
}
.wheel-modal-media img {
  width: 82%;
  max-height: 100%;
  object-fit: contain;
  filter: drop-shadow(0 30px 40px rgba(1, 20, 15, 0.45));
  border-radius: var(--radius, 14px);
}

/* Papirkortet: Mari Delis egen innpakningspapir-tekstur i stedet for en
   flat farge — modalen leser som varen pakket inn over disken.

   Bruker foodpaper.WEBP, ikke original-PNG-en: den lå med en bred
   transparent marg rundt selve arket (1057×1558 der arket bare var
   881×1340), og med background-size: cover havnet den margen inni
   kortet — papiret dekket bare en stripe på midten, med papirfargen
   synlig som lyse kanter i hver side. Webp-en er beskåret til arket og
   gjort ugjennomsiktig, så teksturen dekker hele flaten. Den veier
   samtidig 34 KB mot PNG-ens 1,4 MB.

   Nesten hvit og nøytral, så den legges MULTIPLY over den varme
   papirfargen: krøllene og «Mari DELI»-vannmerket kommer gjennom, men
   flaten holder husets varme tone i stedet for å bli kald grå. cover,
   ikke stretch — krøllene skal ikke smøres ut på tvers når kortet er
   bredt. */
.wheel-modal-scroll {
  position: relative;
  z-index: 1;
  background-color: var(--paper, #fffef4);
  background-image: url("/img/foodpaper.webp");
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  background-blend-mode: multiply;
  border-radius: 22px;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  box-shadow: 0 40px 80px rgba(1, 20, 15, 0.35);
}
.wheel-modal-body {
  /* Toppolstringen må dekke BÅDE overhenget fra .wheel-modal-media og
     litt luft over tittelen — ellers legger objektet seg oppå headeren. */
  padding: clamp(120px, 15vh, 168px) clamp(24px, 4vw, 48px) 44px;
  text-align: center;
}
.wheel-modal-title {
  margin: 0 0 14px;
  font-family: var(--font-mega);
  font-weight: 400;
  font-size: clamp(1.8rem, 3.2vw, 2.6rem);
  color: var(--ink);
}
.wheel-modal-text {
  margin: 0 auto;
  max-width: 46ch;
  color: var(--ink-soft);
  line-height: 1.65;
}
/* Rik variant (produktene): flere avsnitt + faktatabell. Venstrestilt —
   en sentrert brødtekst over flere avsnitt blir tung å lese. */
.wheel-modal-text.is-rich { text-align: left; max-width: 52ch; }
.wheel-modal-text.is-rich p { margin: 0 0 14px; }
.wheel-modal-lead {
  color: var(--ink);
  font-size: 1.08rem;
  line-height: 1.55;
}
.wheel-modal-facts {
  margin: 22px 0 0;
  padding-top: 18px;
  border-top: 1px solid var(--line);
  display: grid;
  gap: 10px;
}
.wheel-modal-facts > div {
  display: flex;
  justify-content: space-between;
  gap: 18px;
}
.wheel-modal-facts dt {
  font-family: var(--font-nav);
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: none;
  color: var(--ink-soft);
}
.wheel-modal-facts dd {
  margin: 0;
  text-align: right;
  color: var(--ink);
}

/* ---------- Storvisning på desktop: objektet ut på SIDEN ----------
   Over 901px legges 3D-objektet/bildet ved siden av papiret i stedet for
   oppå det, og henger godt ut over kortets venstre kant. Media tas ut av
   flyten (absolutt) — da fyller papirkortet hele panelet, og
   lukkekrysset (ankret til panelet) lander nøyaktig i papirets øvre
   høyre hjørne, slik det skal.

   Panelet forskyves til høyre med margin-left for å gi plass til
   overhenget, slik at komposisjonen som HELHET står midt på skjermen —
   ikke papiret alene med objektet hengende ut i intet. */
@media (min-width: 901px) {
  .wheel-modal-panel {
    /* Objektets størrelse og hvor stor andel av det som henger utenfor
       papiret, som variabler: BÅDE grid-kolonnen og objektets egen
       venstrekant regnes av dem, så de to kan ikke gli fra hverandre.
       (Med en fritt valgt kolonnebredde og left: 0 endte objektet 163px
       ute i løse luften i stedet for på papirkanten.) */
    /* Dobbelt så stort som den stablede varianten (som topper på 520px)
       — plassen finnes her, siden objektet ligger ved siden av teksten
       og ikke stjeler høyde fra den. */
    --modal-obj: clamp(520px, 44vw, 800px);
    --modal-obj-out: 0.62; /* andel av objektet som stikker utenfor kanten */
    width: min(92vw, 1360px);
    display: grid;
    /* Kolonne 1 er nøyaktig overhenget. Da fyller komposisjonen (objekt
       + papir) panelboksen presis, og flex-sentreringen i .wheel-modal
       midtstiller HELHETEN — ikke papiret alene med objektet hengende
       utenfor på den ene siden. */
    grid-template-columns: calc(var(--modal-obj) * var(--modal-obj-out)) minmax(0, 1fr);
    align-items: center;
    gap: 0;
  }
  .wheel-modal-media {
    /* Ut av flyten: papiret (grid-kolonne 2) fyller da panelet alene, og
       objektet legger seg over venstre kant uten å presse noe. */
    position: absolute;
    left: calc(var(--modal-obj) * var(--modal-obj-out)); /* = papirets venstrekant */
    top: 50%;
    width: var(--modal-obj);
    height: var(--modal-obj);
    /* Litt over halve objektet havner dermed UTENFOR papirkanten.
       Panelet har overflow: visible, så ingenting klippes. */
    transform: translate(calc(var(--modal-obj-out) * -100%), -50%);
    margin: 0;
  }
  .wheel-modal-scroll {
    grid-column: 2;
    max-height: min(84svh, 800px);
  }
  .wheel-modal-body {
    /* Ingen dyp toppolstring lenger — objektet ligger ikke over teksten,
       det ligger ved siden av.

       Venstremargen REGNES av objektets egen inntrengning i papiret
       (den delen som ikke henger utenfor), pluss litt luft — ikke gjettet
       med en clamp. Et fast tall traff bare den ene modellen: skinka er
       bred og lav, salamien lang og smal, og hver av dem fyller
       canvas-boksen ulikt. Med margen bundet til samme variabler som
       plasseringen kan teksten aldri havne under objektet, uansett
       modell eller skjermbredde. */
    padding: clamp(48px, 6vh, 72px) clamp(32px, 3.5vw, 56px) clamp(44px, 6vh, 64px)
      calc(var(--modal-obj) * (1 - var(--modal-obj-out)) + 24px);
    text-align: left;
  }
  .wheel-modal-text,
  .wheel-modal-text.is-rich { margin-inline: 0; text-align: left; }
}

body.wheel-modal-open { overflow: hidden; }

