← Blurr Motion content-theme-section-kinetic
Categorie content Tier 1 Techniek #10 Deps

BLACK

System default.

ACID

Voltage on.

CORAL

Heat rising.

RESET

Back to source.

1. Mechanisme — kopieer 1-op-1, geen styling-keuzes
// Mechanisme: content-theme-section-kinetic (techniek #10 — theme-shift on scroll)
// IntersectionObserver per sectie -> CSS custom-property swap (--bg/--fg/--accent) op .theme-stage.
// Snappy 0.4s power4.out transition op CSS-vars. Vier paletten: ink -> acid -> coral -> ink-end.
// Reduced-motion: zet eindstate (laatste palette), geen transitions.
const reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
const stage = document.querySelector('.theme-stage');
const palettes = {
  ink:   { bg: '#0A0A0A', fg: '#F4F1EB', accent: '#FFE600' },
  acid:  { bg: '#FFE600', fg: '#0A0A0A', accent: '#FF4D2E' },
  coral: { bg: '#FF4D2E', fg: '#0A0A0A', accent: '#FFE600' },
  end:   { bg: '#0A0A0A', fg: '#FFE600', accent: '#FF4D2E' },
};
const apply = (key) => {
  const p = palettes[key]; if (!p || !stage) return;
  stage.style.setProperty('--bg', p.bg);
  stage.style.setProperty('--fg', p.fg);
  stage.style.setProperty('--accent', p.accent);
};
if (stage) {
  const sections = stage.querySelectorAll('[data-palette]');
  if (reduce) {
    apply(sections[sections.length - 1]?.dataset.palette || 'ink');
  } else {
    apply('ink');
    const io = new IntersectionObserver((entries) => {
      entries.forEach(e => { if (e.isIntersecting) apply(e.target.dataset.palette); });
    }, { threshold: 0.55 });
    sections.forEach(s => io.observe(s));
  }
}
2. Skeleton — DOM + class-namen, mag herschikken
<!-- Skeleton: content-theme-section-kinetic -->
<div class="theme-stage">
  <section data-palette="ink"><h2>BLACK</h2><p>System default.</p></section>
  <section data-palette="acid"><h2>ACID</h2><p>Voltage on.</p></section>
  <section data-palette="coral"><h2>CORAL</h2><p>Heat rising.</p></section>
  <section data-palette="end"><h2>RESET</h2><p>Back to source.</p></section>
</div>
3. Styling-template — verplicht eigen invulling per merk
/* Styling: content-theme-section-kinetic — Archivo Black, oversize, snappy 0.4s */
.theme-stage {
  --bg: #0A0A0A;
  --fg: #F4F1EB;
  --accent: #FFE600;
  background: var(--bg);
  color: var(--fg);
  transition: background 0.4s cubic-bezier(.7,0,.2,1), color 0.4s cubic-bezier(.7,0,.2,1);
  font-family: 'Archivo Black', 'Anton', 'Archivo', sans-serif;
}
.theme-stage section {
  min-height: 100vh;
  display: grid;
  place-content: center;
  padding: clamp(3rem, 8vw, 6rem);
}
.theme-stage h2 {
  font-size: clamp(5rem, 18vw, 16rem);
  line-height: 0.85;
  letter-spacing: -0.04em;
  margin: 0;
  text-transform: uppercase;
}
.theme-stage h2 .dot {
  display: inline-block;
  width: 0.6em; height: 0.15em;
  background: var(--accent);
  margin-left: 0.2em;
  vertical-align: 0.2em;
  transition: background 0.4s;
}
.theme-stage p {
  font-family: 'Archivo', sans-serif;
  font-weight: 700;
  font-size: clamp(1rem, 1.5vw, 1.4rem);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  margin: 1.5rem 0 0;
}