/* ---- 1. Tokens -------------------------------------------------- */
:root{
  /* Palette — the four supplied colours, kept exactly, plus the two the
     spec adds because the four contain no body-text colour. Contrast
     against --bg: bg-deep 1.33:1 (surface only), periwinkle 3.15:1
     (structure only), cyan 9.93:1, label 6.35:1, text 13.76:1.
     On --bg-deep: text 10.33:1, label 4.76:1. All computed, not eyeballed. */
  --bg:#0B2447;
  --bg-deep:#19376D;
  --periwinkle:#576CBC;
  --cyan:#A5D7E8;
  --label:#8FA6D8;
  --text:#EAF3F8;

  /* Depth: one base, veiled. Never a lighter colour — white alpha only.
     A multi-step blue ramp is what makes dark-blue pages look muddy. */
  --fill-1:rgba(255,255,255,.02);
  --fill-2:rgba(255,255,255,.04);
  --fill-3:rgba(255,255,255,.06);
  --line-subtle:rgba(255,255,255,.06);
  --line:rgba(255,255,255,.10);
  --line-hover:rgba(255,255,255,.24);

  /* Three curves, three jobs. */
  --ease-out:cubic-bezier(.12,.23,.17,.99);
  --ease-inout:cubic-bezier(.44,0,.56,1);
  --ease-quint:cubic-bezier(.22,1,.36,1);

  /* Rhythm */
  --pad-block:clamp(5rem,7vw,9rem);
  --gutter:clamp(1.25rem,4vw,3rem);
  --maxw:1240px;

  /* Nested radius ladder: inner = outer − padding */
  --r-pill:40px;
  --r-pill-in:26px;
  --r-card:15px;
  --r-card-in:10px;
  --r-btn:12px;

  --font-sans:'Geist','Geist Fallback',system-ui,-apple-system,sans-serif;
  --font-serif:'Instrument Serif','Instrument Serif Fallback',Georgia,serif;
  --font-mono:'JetBrains Mono','JetBrains Mono Fallback',ui-monospace,monospace;
}

/* ---- 2. Fonts -------------------------------------------------
   Generated by dev/font-metrics.py. Do not hand-edit; regenerate.
   Self-hosted latin subsets. Zero external requests at runtime. */

@font-face {
  font-family: 'Geist';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(fonts/geist-var.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Geist Fallback';
  font-style: normal;
  font-weight: 100 900;
  src: local("Arial");
  size-adjust: 105.80%;
  ascent-override: 94.99%;
  descent-override: 27.88%;
  line-gap-override: 0.00%;
}

@font-face {
  font-family: 'Instrument Serif';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url(fonts/instrument-serif-italic-400.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Instrument Serif Fallback';
  font-style: italic;
  font-weight: 400;
  src: local("Arial");
  size-adjust: 81.08%;
  ascent-override: 122.10%;
  descent-override: 38.23%;
  line-gap-override: 0.00%;
}

@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(fonts/jetbrains-mono-400.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'JetBrains Mono Fallback';
  font-style: normal;
  font-weight: 400;
  src: local("Arial");
  size-adjust: 135.93%;
  ascent-override: 75.04%;
  descent-override: 22.07%;
  line-gap-override: 0.00%;
}

/* ---- 3. Reset + base -------------------------------------------- */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
body{
  margin:0;
  background:var(--bg);
  color:var(--text);
  font-family:var(--font-sans);
  font-size:1.1875rem;   /* 19px — generous relative to headings, on purpose */
  line-height:1.55;
  font-weight:400;
  -webkit-font-smoothing:antialiased;
  /* clip, not hidden: does not create a scroll container, so sticky works */
  overflow-x:clip;
}
img{display:block;max-width:100%;height:auto}
a{color:inherit}
h1,h2,h3{margin:0;font-weight:400}   /* display weight is always 400 */
p{margin:0}
ul,ol{margin:0;padding:0;list-style:none}
:focus-visible{outline:2px solid var(--cyan);outline-offset:3px;border-radius:2px}
.skip{
  position:absolute;left:var(--gutter);top:.5rem;z-index:60;
  padding:.6rem 1rem;border-radius:var(--r-btn);
  background:var(--cyan);color:var(--bg);text-decoration:none;
  transform:translateY(-200%);transition:transform 200ms var(--ease-out);
}
.skip:focus{transform:none}
.vh{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}

/* ---- 4. Primitives ---------------------------------------------- */
.wrap{width:100%;max-width:var(--maxw);margin-inline:auto;padding-inline:var(--gutter)}
.section{padding-block:var(--pad-block);position:relative}
.page{position:relative;z-index:1;background:var(--bg)}

h2{font-size:clamp(1.9rem,4vw,2.8rem);line-height:1.08;letter-spacing:-.015em;max-width:26ch}
h3{font-size:clamp(1.15rem,1.6vw,1.5rem);line-height:1.25}

/* Mono labels are Title Case, never uppercase. 'zero' + tabular-nums so
   counting digits do not jitter. */
.eyebrow{
  font-family:var(--font-mono);font-size:.8rem;line-height:1.3;
  color:var(--label);margin:0 0 1.25rem;
  font-feature-settings:'zero' on;font-variant-numeric:tabular-nums;
}
.lede{max-width:58ch;margin-top:1.25rem;opacity:.78}  /* -> #B9C5D1, 8.82:1 */
.small{font-size:1rem;line-height:1.5}

/* Hairline that dissolves at both ends */
.rule{
  height:1px;border:0;margin:0;
  background:linear-gradient(90deg,
    rgba(165,215,232,.04) 0%,rgba(165,215,232,.18) 50%,rgba(165,215,232,.04) 100%);
}

/* Top-lit surface: bright at top, dark at bottom — one overhead light.
   The light is tinted cyan rather than white so it stays in palette. */
.card{
  position:relative;
  background:var(--fill-2);
  border-radius:var(--r-card);
  padding:1.6rem;
}
.card::after{
  content:'';position:absolute;inset:0;pointer-events:none;z-index:1;
  border:1px solid var(--line);border-radius:inherit;
  background:linear-gradient(0deg,rgba(11,36,71,.35) 0%,rgba(165,215,232,.14) 100%);
  transition:border-color 320ms var(--ease-quint);
}
.card:hover::after{border-color:var(--line-hover)}
.card>*{position:relative;z-index:2}   /* content above the top-lit overlay */

/* The one filled button on the page. Everything else is .link. */
.btn{
  display:inline-flex;align-items:center;gap:.6rem;
  font-family:var(--font-sans);font-size:1rem;font-weight:500;line-height:1;
  padding:.95rem 1.4rem;border:0;border-radius:var(--r-btn);cursor:pointer;
  text-decoration:none;background:var(--cyan);color:var(--bg);
  box-shadow:inset 0 0 0 1px rgba(11,36,71,.18),inset 0 -2px 0 rgba(11,36,71,.06);
  transition:box-shadow 320ms var(--ease-quint),transform 320ms var(--ease-quint);
}
.btn:hover{
  transform:translateY(-1px);
  box-shadow:inset 0 0 0 1px rgba(11,36,71,.18),inset 0 -2px 0 rgba(11,36,71,.06),
             0 0 34px rgba(165,215,232,.30);
}
.link{
  background:none;border:0;padding:0;font:inherit;color:var(--text);cursor:pointer;
  text-decoration:underline;text-decoration-thickness:.5px;text-underline-offset:8px;
  transition:color 320ms var(--ease-quint);
}
.link:hover{color:var(--cyan)}

/* Placeholder markers — deliberately visible. Spec §9: no fact gets
   invented, and a gap on screen beats a gap nobody notices. */
.todo{
  background:none;color:var(--cyan);
  outline:1px solid var(--periwinkle);outline-offset:1px;
  border-radius:4px;padding:0 .3em;
}

/* ---- 5. Header + footer ----------------------------------------- */
.hdr{
  position:sticky;top:0;z-index:30;
  background:rgba(11,36,71,.72);
  -webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);
  border-bottom:1px solid var(--line-subtle);
}
.hdr__in{display:flex;align-items:center;justify-content:space-between;gap:1rem;min-height:4rem}
.mark{
  font-size:1.05rem;font-weight:600;letter-spacing:.14em;text-transform:uppercase;
  text-decoration:none;white-space:nowrap;
}
/* Three links fit at any width, so there is no hamburger and no JS here. */
.nav{display:flex;gap:.9rem}
@media (max-width:420px){.nav a{font-size:.72rem}.mark{font-size:.95rem;letter-spacing:.1em}.hdr__in{gap:.5rem}}
@media (min-width:768px){.nav{gap:1.75rem}}
.nav a{
  font-family:var(--font-mono);font-size:.8rem;color:var(--label);text-decoration:none;
  transition:color 320ms var(--ease-quint);
}
.nav a:hover,.nav a[aria-current="page"]{color:var(--cyan)}

.ftr{
  /* positioned + stacked above the fixed hero media on the home page */
  position:relative;z-index:1;
  background:var(--bg-deep);           /* one of only two --bg-deep uses */
  border-top:1px solid var(--line-subtle);
  padding-block:3.5rem 2.5rem;
}
.ftr__grid{display:grid;gap:2rem;grid-template-columns:1fr}
@media (min-width:768px){.ftr__grid{grid-template-columns:1.4fr 1fr 1fr}}
.ftr a{text-decoration:none;transition:color 320ms var(--ease-quint)}
.ftr a:hover{color:var(--cyan)}
.ftr__social{display:flex;gap:1.25rem;margin-top:.5rem}
.ftr__meta{margin-top:2.5rem;padding-top:1.5rem;border-top:1px solid var(--line-subtle);
  font-family:var(--font-mono);font-size:.8rem;color:var(--label)}

/* ---- 6. Hero ---------------------------------------------------- */
.hero{
  position:relative;
  min-height:100vh;
  min-height:100svh;      /* svh so mobile browser chrome cannot clip it */
  display:grid;align-items:end;
  padding-block:9rem 5rem;
}

.hero__media{
  position:fixed;inset:0;z-index:0;overflow:hidden;
  background:var(--bg);
  isolation:isolate;      /* confines the blobs' screen blend to this box */
}
.hero__img{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;
  object-position:72% 40%;   /* pushed off-centre, per spec */
  /* .50 is BOTH the rest state and the no-JS final state. Task 5 animates
     from here; with JS off nothing moves and this is simply correct. */
  opacity:.50;
  will-change:opacity,transform;
}
/* The DJ sits at ~50% of the photo. Off-centre only pays off on wide screens;
   on a portrait phone the crop is horizontal and 72% cut him in half. */
@media (max-width:900px){.hero__img{object-position:50% 40%}}
/* Warm tungsten stage light pulled cool optically: at half opacity over
   --bg with two --periwinkle blobs on screen blend above, no duotone grade
   or colour processing is needed. */
.hero__scrim{
  position:absolute;inset:0;
  background:linear-gradient(180deg,
    rgba(11,36,71,.20) 0%,
    rgba(11,36,71,.10) 35%,
    rgba(11,36,71,.55) 72%,
    rgba(25,55,109,.88) 100%);   /* --bg-deep floor: one of its two uses */
}

.blob{
  position:absolute;border-radius:50%;pointer-events:none;
  mix-blend-mode:screen;
  background:radial-gradient(closest-side,rgba(87,108,188,.55),rgba(87,108,188,0));
}
/* Durations deliberately mismatched (11s / 14s) so the two never re-sync. */
.blob--a{width:56vw;height:56vw;left:-10vw;top:4vh;filter:blur(54px);
  animation:blobA 11s var(--ease-inout) infinite}
.blob--b{width:46vw;height:46vw;right:-8vw;bottom:-6vh;filter:blur(62px);
  animation:blobB 14s var(--ease-inout) infinite}
@keyframes blobA{0%,100%{transform:scale(1)}50%{transform:scale(1.07)}}
@keyframes blobB{0%,100%{transform:scale(1)}50%{transform:scale(1.12)}}

.hero__copy{position:relative;z-index:2;will-change:opacity,transform}

/* The two-typeface headline: crowded grotesque above, airy italic serif
   below. The mismatch in line-height is the effect, not an accident. */
.hero__h{display:grid;margin-top:1.1rem}
.hero__l1{
  display:block;font-family:var(--font-sans);font-weight:400;
  font-size:clamp(2.25rem,6vw,3.9rem);line-height:.88;letter-spacing:-.02em;
}
.hero__l2{
  display:block;font-family:var(--font-serif);font-style:italic;font-weight:400;
  font-size:clamp(2.35rem,6.4vw,4.1rem);line-height:1.35;letter-spacing:0;
}
[data-word]{display:inline-block}   /* transform + blur need a block box */

.hero__eyebrow{margin:0}

/* ---- 7. Marquee ------------------------------------------------- */
/* Already in motion as it enters view — that is what carries the eye past
   the fold. This is where arrakis puts its partner logos. */
.marquee{
  position:relative;overflow:hidden;
  padding-block:1.15rem;
  border-block:1px solid var(--line-subtle);
  /* A mask, not a gradient overlay: it needs no knowledge of the colour
     behind it, so it cannot desync from the background. */
  -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 12%,#000 88%,transparent 100%);
  mask-image:linear-gradient(90deg,transparent 0,#000 12%,#000 88%,transparent 100%);
}
.marquee__track{display:flex;width:max-content;animation:mq 24s linear infinite}
.marquee:hover .marquee__track{animation-play-state:paused}
.marquee__set{display:flex}
.marquee__item{
  display:flex;align-items:center;gap:1.75rem;padding-inline:.875rem;
  font-family:var(--font-mono);font-size:.8rem;color:var(--label);white-space:nowrap;
}
.marquee__item::after{
  content:'';flex:0 0 auto;width:4px;height:4px;border-radius:50%;background:var(--periwinkle);
}
/* -25%, not -100%: the track holds four identical sets, so a quarter of it is
   exactly one set wide and the wrap lands on a matching frame. Four, not two:
   one set is narrower than a wide desktop viewport, and with two sets the
   right edge ran out of text halfway through the loop (a visible gap). */
@keyframes mq{from{transform:translate3d(0,0,0)}to{transform:translate3d(-25%,0,0)}}

/* Marks a block whose entire content is a guess. Removing the class is the
   one-word change once the real content exists. */
.todo-zone{outline:1px dashed var(--periwinkle);outline-offset:-1px}

/* ---- 8. Lightbox ------------------------------------------------ */
.lightbox{
  border:0;padding:0;background:transparent;color:var(--text);
  max-width:min(96vw,1300px);max-height:92vh;
}
.lightbox::backdrop{background:rgba(5,16,34,.88)}
.lightbox img{max-height:86vh;width:auto;border-radius:var(--r-card-in)}
.lightbox button{
  position:absolute;top:.5rem;right:.5rem;width:2.5rem;height:2.5rem;border-radius:50%;
  border:0;background:rgba(11,36,71,.8);color:var(--text);font-size:1.4rem;line-height:1;cursor:pointer;
}

/* ---- 9. Feesten + Referenties ----------------------------------- */
.lede--wide{max-width:64ch}
.stack>*+*{margin-top:1.1rem}
.cols{display:grid;gap:2.5rem;align-items:center}
@media (min-width:900px){.cols{grid-template-columns:1fr 1fr;gap:4rem}.cols--flip>:first-child{order:2}}
.pic{border-radius:var(--r-card);width:100%;height:auto}

.cards{display:grid;gap:1.5rem;margin-top:2.5rem}
@media (min-width:900px){.cards--3{grid-template-columns:repeat(3,1fr)}}
@media (min-width:640px) and (max-width:899px){.cards--4{grid-template-columns:repeat(2,1fr)}}
@media (min-width:900px){.cards--4{grid-template-columns:repeat(2,1fr)}}
.card--occ{display:flex;flex-direction:column;gap:1rem}
.card--occ .pic{border-radius:var(--r-card-in);aspect-ratio:3/2;object-fit:cover}
.card--occ p{opacity:.78;font-size:1.05rem}
.card--occ .link{margin-top:auto;align-self:flex-start}
.card h3+p{margin-top:.6rem;opacity:.78;font-size:1.05rem}

/* ---- 10. Over + Licht & Geluid ---------------------------------- */
.pillars{display:grid;gap:1.5rem;margin-top:2.5rem}
@media (min-width:900px){.pillars{grid-template-columns:repeat(3,1fr)}}
.pillar__n{font-family:var(--font-mono);font-size:.8rem;color:var(--label);margin-bottom:.9rem}

.timeline{margin-top:2.5rem;border-top:1px solid var(--line-subtle)}
.timeline li{
  display:grid;gap:.25rem 2rem;padding-block:1rem;
  border-bottom:1px solid var(--line-subtle);
}
@media (min-width:640px){.timeline li{grid-template-columns:8rem 1fr;align-items:baseline}}
.timeline__y{font-family:var(--font-mono);font-size:.8rem;color:var(--cyan)}
.timeline__t{font-size:1.05rem;opacity:.86}

.callout{
  margin-top:2rem;padding:1.5rem 1.75rem;border-radius:var(--r-card);
  background:var(--fill-3);border-left:3px solid var(--cyan);
  font-size:1.25rem;line-height:1.4;
}
.cta-row{display:flex;flex-wrap:wrap;align-items:center;gap:1.5rem;margin-top:2rem}

/* Page header for the inner pages (the home page has the fixed hero). */
.phead{padding-block:clamp(4rem,8vw,7rem) 0}
.phead__h{
  font-size:clamp(2.4rem,6.4vw,4.2rem);line-height:1.02;letter-spacing:-.02em;max-width:18ch;
}
.phead .lede{max-width:60ch}
.phead .pic{margin-top:3rem;aspect-ratio:16/8;object-fit:cover}

/* ---- 11. Mix ---------------------------------------------------- */
.gallery{display:grid;gap:.75rem;margin-top:2.5rem;grid-template-columns:repeat(2,1fr)}
@media (min-width:900px){.gallery{grid-template-columns:repeat(4,1fr);gap:1rem}}
.gallery a{display:block;border-radius:var(--r-card-in);overflow:hidden;aspect-ratio:4/3;background:var(--fill-2)}
.gallery img{width:100%;height:100%;object-fit:cover;transition:transform 600ms var(--ease-quint)}
.gallery a:hover img{transform:scale(1.04)}
.caption{margin-top:1.25rem;font-family:var(--font-mono);font-size:.8rem;color:var(--label)}

/* ---- 12. FAQ + Boeken ------------------------------------------- */
.cta{text-align:center}
.cta h2{margin-inline:auto}
.cta .lede{margin-inline:auto}
.cta .cta-row{justify-content:center}
.contact-lines{margin-top:1.75rem;display:grid;gap:.4rem;justify-items:center}
.contact-lines a{text-decoration-thickness:.5px;text-underline-offset:6px}

.contact{max-width:34rem;margin-inline:auto;text-align:center}
.contact .lede{margin-inline:auto}
.contact__list{margin:2.5rem 0 0;text-align:left;border-top:1px solid var(--line-subtle)}
.contact__list div{
  display:flex;justify-content:space-between;gap:1.5rem;flex-wrap:wrap;
  padding-block:1rem;border-bottom:1px solid var(--line-subtle);
}
.contact__list dt{font-family:var(--font-mono);font-size:.8rem;color:var(--label);padding-top:.25rem}
.contact__list dd{margin:0}
.tip{margin-top:2.5rem;opacity:.78;font-size:1.05rem;text-align:left}

/* ---- 13. Motion + reduced motion -------------------------------- */
/* .will-reveal is added BY main.js, never present in static markup. With
   JavaScript off it is never applied, so content renders in its final
   state — acceptance criterion 5, satisfied structurally. */
.will-reveal{
  opacity:.001;
  filter:blur(4px);
  transform:translateY(12px);
}
.will-reveal.is-in{
  opacity:1;filter:blur(0);transform:none;
  transition:opacity 800ms var(--ease-out),
             filter 800ms var(--ease-out),
             transform 800ms var(--ease-out);
}
/* Hand-authored delay ladder for grouped items: 0 / 0.1 / 0.2s.
   Three rungs, written out. Not a stagger function. */
.will-reveal[data-reveal-delay="1"].is-in{transition-delay:.1s}
.will-reveal[data-reveal-delay="2"].is-in{transition-delay:.2s}

/* Reduced motion means NO motion, not less: module 2 in main.js returns
   before the scroll loop ever starts, and this block hard-stops everything
   CSS drives. scroll-behavior is reset because section 3 sets it to smooth,
   which would otherwise animate every anchor jump for a user who asked for
   no animation. .marquee__track arrives in Task 6. */
@media (prefers-reduced-motion: reduce){
  html{scroll-behavior:auto}
  [data-word],[data-reveal],.will-reveal{
    opacity:1 !important;
    filter:none !important;
    transform:none !important;
    transition:none !important;
  }
  .marquee__track,.blob{animation:none !important}
}
