/* ==========================================================================
   CHRISTINE PRODUCTIES — CONTACTAFDRUK
   Fotogalerij + lichtbak. Geldt op alle schermbreedtes: dit is een nieuwe
   sectie, dus mobiel moest hier wél een eigen ontwerp krijgen.

   HET IDEE
   Een contactafdruk is het vel waarop een fotograaf al zijn negatieven naast
   elkaar afdrukt om te kiezen. Dat is precies wat dit blok is: het archief
   van het atelier, met framenummers, kaderhoeken en een loep.

   MOBIEL   horizontale strook met snap, één-en-een-beetje beeld tegelijk.
   DESKTOP  gebroken raster van tien tegels dat zich herhaalt, uitlopend tot
            de rechterschermrand.
   ========================================================================== */


/* De afstand van de rand van .wrap tot de schermrand. Hiermee kan een blok
   exact tot de rand uitlopen, ook als het in de mastheadkolom staat — een
   percentage zou tegen de kolombreedte rekenen en er dus naast zitten. */
:root{ --cp-gutter:calc((100vw - min(var(--max),90vw)) / 2) }

/* ==========================================================================
   1. DE SECTIE
   ========================================================================== */

.gal-sec{ overflow:hidden }

.gal-head{
  display:flex;
  align-items:baseline;
  justify-content:space-between;
  gap:1.5rem;
  flex-wrap:wrap;
  margin-top:var(--s-4);
  padding-bottom:var(--s-3);
  border-bottom:1px solid var(--line-d);
}
.gal-count{
  font-size:var(--fs-label);
  font-weight:800;
  letter-spacing:var(--track-label);
  text-transform:uppercase;
  color:var(--red-soft);
  font-variant-numeric:tabular-nums;
}
.gal-hint{
  font-size:var(--fs-label);
  font-weight:800;
  letter-spacing:var(--track-label);
  text-transform:uppercase;
  color:color-mix(in oklab,var(--white) 38%,transparent);
}


/* ==========================================================================
   2. MOBIEL — horizontale strook
   Uitgangspunt, want dit is de smalste maat. Desktop bouwt hier bovenop.
   ========================================================================== */

.gal{
  display:flex;
  gap:12px;
  margin-top:var(--s-4);
  padding-bottom:14px;
  overflow-x:auto;
  overscroll-behavior-x:contain;
  scroll-snap-type:x mandatory;
  -webkit-overflow-scrolling:touch;
  scrollbar-width:none;
  /* Loopt door tot de rechterschermrand: je ziet dat er meer is. */
  margin-inline-end:calc(var(--cp-gutter) * -1);
  padding-inline-end:5vw;
}
.gal::-webkit-scrollbar{ display:none }

.gal-item{
  position:relative;
  flex:0 0 76%;
  scroll-snap-align:start;
  aspect-ratio:3/4;
  margin:0;
  overflow:hidden;
  background:#211c21;
  border:1px solid color-mix(in oklab,var(--white) 10%,transparent);
  cursor:pointer;
  padding:0;
  display:block;
  color:inherit;
  font:inherit;
  text-align:left;
}
.gal-item img{
  width:100%;
  height:100%;
  object-fit:cover;
  filter:saturate(.94) contrast(1.03);
  transition:scale .8s var(--ease-lens),filter .5s linear;
}

/* Framenummer linksboven, zoals op een negatiefstrook. */
.gal-item b{
  position:absolute;
  top:10px; left:10px;
  z-index:2;
  padding:4px 7px;
  background:color-mix(in oklab,var(--ink) 72%,transparent);
  backdrop-filter:blur(6px);
  color:var(--red-soft);
  font:800 10px/1 "Manrope",sans-serif;
  letter-spacing:.16em;
  font-variant-numeric:tabular-nums;
}
/* Onderrand met vignet, zodat het nummer altijd leesbaar blijft. */
.gal-item::after{
  content:"";
  position:absolute;
  inset:0;
  z-index:1;
  pointer-events:none;
  background:linear-gradient(180deg,rgba(0,0,0,.34),transparent 30%,transparent 74%,rgba(0,0,0,.3));
}

.gal-empty{
  flex:1;
  padding:2.5rem 1.25rem;
  border:1px dashed color-mix(in oklab,var(--white) 18%,transparent);
  color:color-mix(in oklab,var(--white) 45%,transparent);
  font-size:var(--fs-sm);
  line-height:1.7;
}


/* ==========================================================================
   3. DESKTOP — gebroken raster
   Tien tegels die zich herhalen. Elke rij telt op tot twaalf kolommen, dus
   het raster blijft sluiten hoeveel foto's je er ook in zet.
     rij A  5 + 7
     rij B  4 + 4 + 4
     rij C  7 + 5
     rij D  4 + 4 + 4
   ========================================================================== */

@media (min-width:901px){

  .gal{
    display:grid;
    grid-template-columns:repeat(12,1fr);
    gap:clamp(10px,1vw,16px);
    overflow:visible;
    padding-bottom:0;
    padding-inline-end:0;
    margin-top:var(--s-5);
  }

  .gal-item{ flex:none; width:auto }

  .gal-item:nth-child(10n+1){ grid-column:span 5; aspect-ratio:4/5 }
  .gal-item:nth-child(10n+2){ grid-column:span 7; aspect-ratio:16/10 }
  .gal-item:nth-child(10n+3),
  .gal-item:nth-child(10n+4),
  .gal-item:nth-child(10n+5){ grid-column:span 4; aspect-ratio:3/4 }
  .gal-item:nth-child(10n+6){ grid-column:span 7; aspect-ratio:16/10 }
  .gal-item:nth-child(10n+7){ grid-column:span 5; aspect-ratio:4/5 }
  .gal-item:nth-child(10n+8),
  .gal-item:nth-child(10n+9),
  .gal-item:nth-child(10n){ grid-column:span 4; aspect-ratio:3/4 }

  /* Een niet-volle laatste rij vult zichzelf op in plaats van een gat te laten. */
  .gal{ grid-auto-flow:dense }
}

/* Ook in de mastheadkolom loopt het raster door tot de rechterschermrand. */
@media (min-width:1100px){
  .gal-sec .gal{ margin-inline-end:calc(var(--cp-gutter) * -1) }
}


/* ==========================================================================
   4. HOVER — de loep
   ========================================================================== */

@media (hover:hover) and (pointer:fine){

  .gal-item{ transition:border-color .3s linear,transform .5s var(--ease-lens) }
  .gal-item:hover{ border-color:var(--edge-red) }
  .gal-item:hover img{ scale:1.045; filter:saturate(1) contrast(1.05) }

  /* Kaderhoeken, dezelfde taal als de productkaarten. */
  .gal-item i{
    position:absolute;
    z-index:3;
    width:16px; height:16px;
    border:1px solid var(--red-soft);
    opacity:0;
    transition:opacity .3s linear,translate .45s var(--ease-lens);
    pointer-events:none;
  }
  .gal-item i:nth-of-type(1){ top:10px; right:10px; border-left:0; border-bottom:0; translate:5px -5px }
  .gal-item i:nth-of-type(2){ bottom:10px; left:10px; border-right:0; border-top:0; translate:-5px 5px }
  .gal-item:hover i{ opacity:1; translate:0 0 }

  .gal-item em{
    position:absolute;
    z-index:3;
    right:10px; bottom:10px;
    padding:5px 9px;
    background:var(--ink);
    color:var(--red-soft);
    font:800 10px/1 "Manrope",sans-serif;
    letter-spacing:.18em;
    font-style:normal;
    text-transform:uppercase;
    opacity:0;
    translate:0 6px;
    transition:opacity .28s linear,translate .35s var(--ease-lens);
  }
  .gal-item:hover em{ opacity:1; translate:0 0 }

  /* De rest dimt zodat de aandacht ergens heen gaat. Precies waar :has()
     voor bedoeld is: een sibling-effect zonder een regel JavaScript. */
  .gal:has(.gal-item:hover) .gal-item:not(:hover){ opacity:.42 }
  .gal-item{ transition:opacity .35s linear,border-color .3s linear }
}


/* ==========================================================================
   5. SCROLL-DRIVEN BINNENKOMST
   ========================================================================== */

@supports (animation-timeline:view()){
  @media (min-width:901px) and (prefers-reduced-motion:no-preference){
    .gal-item{
      animation:galIn linear both;
      animation-timeline:view();
      animation-range:entry 0% entry 55%;
    }
    @keyframes galIn{
      from{ opacity:0; translate:0 2.5rem; scale:.97 }
      to  { opacity:1; translate:0 0; scale:1 }
    }
    /* Het hoverdimmen mag de binnenkomst niet overschrijven. */
    .gal:has(.gal-item:hover) .gal-item:not(:hover){ opacity:.42 }
  }
}


/* ==========================================================================
   6. LICHTBAK
   Native <dialog>: krijgt focusbeheer, Escape en de bovenste laag gratis van
   de browser, zonder eigen z-index-oorlog.
   ========================================================================== */

.lb{
  width:100vw;
  max-width:100vw;
  height:100dvh;
  max-height:100dvh;
  margin:0;
  padding:0;
  border:0;
  background:transparent;
  color:#fff;
  overflow:hidden;
}
.lb::backdrop{
  background:color-mix(in oklab,var(--ink) 92%,transparent);
  backdrop-filter:blur(16px);
}

.lb-in{
  position:relative;
  height:100%;
  display:grid;
  grid-template-rows:auto 1fr auto;
  padding:14px;
  gap:12px;
}

.lb-top{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:1rem;
}
.lb-frame{
  display:flex;
  align-items:center;
  gap:12px;
  font-size:var(--fs-label);
  font-weight:800;
  letter-spacing:var(--track-label);
  text-transform:uppercase;
  color:var(--red-soft);
  font-variant-numeric:tabular-nums;
}
.lb-frame s{
  width:34px; height:1px;
  background:color-mix(in oklab,var(--white) 30%,transparent);
  text-decoration:none;
}

.lb-close{
  width:46px; height:46px;
  border:1px solid color-mix(in oklab,var(--white) 26%,transparent);
  border-radius:50%;
  background:transparent;
  color:#fff;
  font-size:18px;
  cursor:pointer;
  transition:background .25s linear,border-color .25s linear;
}
.lb-close:hover{ background:var(--red); border-color:var(--red) }

.lb-stage{
  position:relative;
  display:grid;
  place-items:center;
  min-height:0;
}
.lb-stage img{
  max-width:100%;
  max-height:100%;
  width:auto;
  height:auto;
  object-fit:contain;
  border:1px solid color-mix(in oklab,var(--white) 14%,transparent);
  opacity:0;
  scale:.985;
  transition:opacity .35s linear,scale .45s var(--ease-lens);
}
.lb-stage img.on{ opacity:1; scale:1 }

.lb-nav{
  position:absolute;
  top:50%;
  translate:0 -50%;
  width:52px; height:52px;
  border:1px solid color-mix(in oklab,var(--white) 26%,transparent);
  border-radius:50%;
  background:color-mix(in oklab,var(--ink) 55%,transparent);
  backdrop-filter:blur(8px);
  color:#fff;
  font-size:20px;
  cursor:pointer;
  transition:background .25s linear,border-color .25s linear;
}
.lb-nav:hover{ background:var(--red); border-color:var(--red) }
.lb-prev{ left:6px }
.lb-next{ right:6px }
.lb-nav[disabled]{ opacity:.28; pointer-events:none }

.lb-bot{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:1rem;
  flex-wrap:wrap;
}
.lb-cap{
  margin:0;
  font-size:var(--fs-cap);
  line-height:1.6;
  color:color-mix(in oklab,var(--white) 66%,transparent);
  max-width:60ch;
}
.lb-keys{
  display:flex;
  gap:14px;
  font-size:var(--fs-label);
  font-weight:800;
  letter-spacing:var(--track-label);
  text-transform:uppercase;
  color:color-mix(in oklab,var(--white) 34%,transparent);
}
.lb-keys kbd{
  font:inherit;
  padding:2px 5px;
  margin-right:5px;
  border:1px solid color-mix(in oklab,var(--white) 20%,transparent);
  border-radius:3px;
}

/* Filmperforatie langs de bovenrand van de lichtbak: hetzelfde signatuur
   als de bestelrail, zodat het bij de site hoort en niet bij een plug-in. */
.lb-in::before{
  content:"";
  position:absolute;
  left:0; right:0; top:0;
  height:7px;
  background-image:repeating-linear-gradient(90deg,
    color-mix(in oklab,var(--paper) 80%,transparent) 0 7px, transparent 7px 18px);
  opacity:.34;
  pointer-events:none;
}

@media (min-width:901px){
  .lb-in{ padding:24px clamp(24px,5vw,64px) }
  .lb-prev{ left:clamp(10px,2vw,28px) }
  .lb-next{ right:clamp(10px,2vw,28px) }
}
@media (max-width:620px){
  .lb-keys{ display:none }
  .lb-nav{ width:44px; height:44px }
}

body.lb-open{ overflow:hidden }


/* ==========================================================================
   7. BEWEGING UIT
   ========================================================================== */

@media (prefers-reduced-motion:reduce){
  .gal-item,.gal-item img,.gal-item i,.gal-item em,
  .lb-stage img,.lb-nav,.lb-close{
    transition:none !important;
    animation:none !important;
  }
  .gal-item{ opacity:1 !important; translate:0 !important; scale:1 !important }
  .lb-stage img{ opacity:1; scale:1 }
  .gal{ scroll-behavior:auto }
}

/* ==========================================================================
   8. COMPACT — de galerij direct onder de introductie
   De strook staat nu vast aan het "hoi ik ben Christine"-blok. Beide zijn
   sec-ink, dus zonder bovenmarge lezen ze als één donker blok: eerst het
   verhaal, dan meteen het beeld.

   MOBIEL   twee-en-een-beetje tegel tegelijk in plaats van één.
   DESKTOP  gelijke kleine tegels die zichzelf over de breedte verdelen,
            in plaats van het gebroken raster met grote uitschieters.
   ========================================================================== */

.gal-compact{
  padding-top:0;
  padding-bottom:clamp(52px,6vw,88px);
}

/* Het introblok erboven mag direct tegen de strook aan staan. Alleen als de
   compacte galerij er echt op volgt — staat hij ergens anders, dan houdt het
   introblok gewoon zijn normale ruimte. Browsers zonder :has() vallen terug
   op die normale ruimte; dat is een grotere marge, geen kapot beeld. */
.about-first:has(+ .gal-compact){
  padding-bottom:clamp(20px,2.4vw,36px);
}

.gal-compact .gal-head{
  margin-top:0;
  padding-bottom:var(--s-2);
}
.gal-compact .gal{ margin-top:var(--s-3) }

/* Mobiel: kleinere tegels, dus meer beeld in één oogopslag. */
.gal-compact .gal-item{
  flex:0 0 42%;
  aspect-ratio:3/4;
}
.gal-compact .gal-item b{
  top:7px; left:7px;
  padding:3px 5px;
  font-size:9px;
}

@media (min-width:901px){
  /* Geen vast 12-koloms raster meer, maar tegels van rond de 165px die
     zichzelf over de breedte verdelen. Op elk scherm dus even kleine
     tegels — breder scherm betekent meer foto's per rij, niet grotere. */
  .gal-compact .gal{
    grid-template-columns:repeat(auto-fill,minmax(clamp(130px,12vw,180px),1fr));
    gap:clamp(8px,.7vw,12px);
    margin-top:var(--s-3);
  }
  /* Overschrijft het gebroken 10n-raster uit blok 3. Twee klassen plus een
     pseudo-klasse weegt zwaarder, dus !important is niet nodig. */
  .gal-compact .gal-item:nth-child(n){
    grid-column:auto;
    aspect-ratio:3/4;
  }
}

/* Compact blijft binnen de kolom staan: het gebroken raster liep bewust tot
   de schermrand door, maar een kleine strook onder de introductie oogt
   netter als hij netjes met de tekst uitlijnt. */
@media (min-width:1100px){
  .gal-sec.gal-compact .gal{ margin-inline-end:0 }
}

/* ==========================================================================
   9. FILMSTROOK — de galerij als onderdeel van het openingsbeeld
   De galerij staat nu in de kolom waar eerst één portret hing. Geen los blok
   verderop meer, maar beeld dat direct naast het verhaal loopt.

   HET IDEE
   Een filmstrook die door de poort van een projector loopt. Je schuift hem
   zelf op en neer; wat in het midden staat is scherp en licht, wat naar de
   rand toe gaat dooft. Langs beide zijden loopt perforatie, en de boven- en
   onderrand vervagen in het donker in plaats van hard af te snijden.

   Alles hieronder hangt aan .gal-reel. Het #gal-element en script-gallery.js
   zijn ongewijzigd: de lichtbak, de framenummers en het inladen werken nog
   precies zoals eerst.
   ========================================================================== */

.about-reel{ position:relative }

/* --- het venster van de projector ---------------------------------------- */

.reel-frame{
  --perf:15px;                      /* breedte van de perforatiestrook */
  position:relative;
  padding-inline:var(--perf);
  background:#141116;
  border:1px solid color-mix(in oklab,var(--white) 11%,transparent);
}

/* Perforatie links en rechts. Een gecentreerde kolom van streepjes binnen de
   strook, zodat het gaatjes lijken en geen doorlopende rand. Zelfde motief
   als de bovenrand van de lichtbak, dus het hoort bij de site. */
.reel-frame::before,
.reel-frame::after{
  content:"";
  position:absolute;
  top:0; bottom:0;
  width:var(--perf);
  z-index:3;
  pointer-events:none;
  background:repeating-linear-gradient(180deg,
    color-mix(in oklab,var(--paper) 82%,transparent) 0 9px,
    transparent 9px 23px) center / 7px 100% no-repeat;
  opacity:.28;
}
.reel-frame::before{ left:0 }
.reel-frame::after{ right:0 }

/* --- de strook zelf ------------------------------------------------------- */

.gal.gal-reel{
  display:grid;
  /* Drie smalle kolommen: een contactafdruk, geen fotokaarten. Zo blijft de
     strook echt klein naast de tekst in plaats van er een tweede blok van
     te maken. */
  grid-template-columns:repeat(3,1fr);
  gap:7px;
  /* De horizontale strook uit blok 2 helemaal terugdraaien. */
  margin:0;
  padding:12px 0;
  overflow-x:hidden;
  overflow-y:auto;
  height:clamp(340px,56vh,540px);
  scroll-snap-type:y proximity;
  overscroll-behavior-y:contain;
  -webkit-overflow-scrolling:touch;
  scrollbar-width:none;
  /* Emulsiefade: boven en onder loopt het beeld weg in het donker in plaats
     van tegen een harde rand te stoppen. */
  -webkit-mask-image:linear-gradient(180deg,transparent 0,#000 10%,#000 90%,transparent 100%);
          mask-image:linear-gradient(180deg,transparent 0,#000 10%,#000 90%,transparent 100%);
}
.gal.gal-reel::-webkit-scrollbar{ display:none }

/* Tegels: alle rasterregels uit blok 2 en 3 worden hier overschreven. Twee
   klassen plus een pseudo-klasse weegt zwaarder dan de nth-child-regels
   daar, dus !important is niet nodig. */
.gal-reel .gal-item:nth-child(n){
  flex:none;
  width:auto;
  grid-column:auto;
  aspect-ratio:3/4;
  scroll-snap-align:center;
}
.gal-reel .gal-item b{
  top:6px; left:6px;
  padding:3px 5px;
  font-size:9px;
  letter-spacing:.12em;
}

/* Het hoverdimmen uit blok 4 hoort hier niet: in de strook doet de
   poortanimatie hieronder dat werk al, en twee effecten op dezelfde
   eigenschap gaan met elkaar vechten. */
.gal-reel:has(.gal-item:hover) .gal-item:not(:hover){ opacity:1 }

/* --- de poort ------------------------------------------------------------- */

@supports (animation-timeline:view()){
  @media (prefers-reduced-motion:no-preference){
    /* view(block) meet ten opzichte van de strook zelf, niet de pagina: het
       effect hangt dus aan hoe jij de strook schuift. */
    .gal-reel .gal-item{
      animation:reelGate linear both;
      animation-timeline:view(block);
      animation-range:cover 0% cover 100%;
    }
    @keyframes reelGate{
      0%  { opacity:.18; scale:.88; filter:saturate(.45) brightness(.62) }
      24% { opacity:1;   scale:1;   filter:saturate(.96) contrast(1.04) brightness(1) }
      76% { opacity:1;   scale:1;   filter:saturate(.96) contrast(1.04) brightness(1) }
      100%{ opacity:.18; scale:.88; filter:saturate(.45) brightness(.62) }
    }
  }
}

/* --- bijschrift onder de strook ------------------------------------------ */

.about-reel .gal-head{
  margin-top:12px;
  padding-bottom:0;
  border-bottom:0;
  gap:.9rem;
  font-size:10px;
}
.about-reel .gal-count,
.about-reel .gal-hint{ font-size:10px }

/* --- kleiner scherm ------------------------------------------------------- */

/* Onder 900px valt .about terug op één kolom, dus de strook wordt breed. Een
   lagere strook houdt het compact: het openingsblok moet niet meteen een
   scherm vol foto's worden. De drie kolommen blijven staan. */
@media (max-width:900px){
  .gal.gal-reel{
    height:clamp(280px,38vh,360px);
  }
  .reel-frame{ --perf:12px }
}

/* --- beweging uit --------------------------------------------------------- */

@media (prefers-reduced-motion:reduce){
  .gal-reel .gal-item{ animation:none !important; opacity:1 !important; scale:1 !important }
  .gal.gal-reel{ scroll-snap-type:none }
}
