/* Bureaublad van Stefan Koop: een tafel van bovenaf. */

:root {
  --felt: #1d3f33;
  --felt-2: color-mix(in srgb, var(--felt) 86%, #e8f0dc);   /* het lichtere midden van de vignet */
  --chalk: #eceee8;
  --chalk-dim: rgba(236, 238, 232, .62);
  --postit: #f5df4d;
  --postit-ink: #1a1a14;
  --ink: #0f1411;

  --font-display: "Alpino", "Arial Black", Helvetica, sans-serif;
  --font-text: "Ranade", system-ui, sans-serif;

  --sh-rest: 0 2px 4px rgba(0, 0, 0, .35), 0 10px 20px rgba(0, 0, 0, .3);
  --sh-drag: 0 6px 12px rgba(0, 0, 0, .42), 0 22px 42px rgba(0, 0, 0, .38);
  --sh-lift: 0 30px 60px rgba(0, 0, 0, .55);

  --gap: clamp(16px, 3vw, 32px);
  --panel-top: 58vh;
  --lift-ease: cubic-bezier(.2, .9, .25, 1.05);
  --bar: clamp(14px, 2.4vw, 26px);
}

*, *::before, *::after { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  background: var(--ink);
  color: var(--chalk);
  font-family: var(--font-text);
  font-size: 17px;
  line-height: 1.5;
  overflow: hidden;
  overscroll-behavior: none;
  -webkit-text-size-adjust: 100%;
  -webkit-font-smoothing: antialiased;
}

/* ---------- de tafel ---------- */

.table {
  position: fixed;
  inset: 0;
  overflow: hidden;
  touch-action: none;
  background: var(--felt);
  /* Lang drukken op een voorwerp gaf op iOS een blauwe selectie over de tafel en
     daarna het deelmenu van het plaatje. De tafel en alles wat erop ligt zijn
     beeld, geen tekst. Het paneel zet het verderop weer aan: daar wil je een
     titel of een zin wel kunnen aanwijzen en kopieren. */
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}

/* Het vilt is een eigen laag: bij het zoomen schaalt hij iets minder mee dan de
   voorwerpen, en dan komt de stapel naar je toe in plaats van het hele plaatje. */
.vilt {
  position: absolute;
  inset: -8%;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(115% 96% at 50% 44%, var(--felt-2) 0%, var(--felt) 66%);
}

/* Fijne ruis over het vilt, uit een feTurbulence data-URI. */
.vilt::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: .07;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* De laag met de voorwerpen is zo groot als de wereld en draagt de camera:
   een enkele transform schuift en zoomt alles tegelijk. */
.items {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  z-index: 1;
  transform-origin: 0 0;
}

/* Een sluier tussen de liggende voorwerpen en het opgetilde voorwerp, zodat de
   tekst in het paneel nooit op een drukke hoes hoeft te leunen. Hij loopt ruim
   over de wereld heen, want de camera mag ook buiten de rand kijken. */
.items::before {
  content: "";
  position: absolute;
  left: var(--sl, -100%);
  top: var(--st, -100%);
  width: var(--sw, 300%);
  height: var(--sh, 300%);
  z-index: 5000;
  background: rgba(10, 18, 14, .5);
  opacity: 0;
  pointer-events: none;
  transition: opacity 300ms ease;
}
.table.is-open .items::before { opacity: 1; }

/* Het licht boven de tafel valt in het midden; de hoeken lopen weg in schaduw.
   Daardoor blijft de tekst in de hoeken leesbaar, ook over een lichte hoes heen. */
.table::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  transition: opacity 300ms ease;
  background:
    radial-gradient(74% 30% at 0% 0%, rgba(11, 16, 13, .72), rgba(11, 16, 13, 0) 72%),
    radial-gradient(66% 26% at 0% 100%, rgba(11, 16, 13, .68), rgba(11, 16, 13, 0) 72%),
    radial-gradient(46% 22% at 100% 100%, rgba(11, 16, 13, .62), rgba(11, 16, 13, 0) 72%);
}
.table.is-open::after { opacity: .3; }

/* ---------- de voorwerpen ---------- */

.item {
  --lift: 0;   /* 0 ligt plat op het vilt, 1 komt naar je toe onder de cursor */
  --sx: 0px;   /* de schaduw sleept tegen de bewegingsrichting in */
  --sy: 0px;
  --zweef: 0;  /* 0 ligt op het vilt, 1 zweeft er los boven */
  position: absolute;
  left: 0;
  top: 0;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  -webkit-appearance: none;
  appearance: none;
  z-index: 10;
  opacity: 0;
  cursor: grab;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  transform-origin: 50% 50%;
  will-change: transform;
  box-shadow:
    calc(var(--sx) * .3) calc(2px + 7px * var(--lift) + 5px * var(--zweef) + var(--sy) * .3)
      calc(4px + 9px * var(--lift) + 7px * var(--zweef)) rgba(0, 0, 0, calc(.35 + .06 * var(--lift) - .04 * var(--zweef))),
    var(--sx) calc(10px + 20px * var(--lift) + 16px * var(--zweef) + var(--sy))
      calc(20px + 26px * var(--lift) + 24px * var(--zweef)) rgba(0, 0, 0, calc(.3 + .1 * var(--lift) - .05 * var(--zweef)));
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
  transition: opacity 320ms ease;
}

/* Wat naar voren komt vangt ook meer licht van de lamp boven de tafel. */
.item .art { filter: brightness(calc(1 + .1 * var(--lift))); }
.item.is-in { opacity: 1; }

.item.is-moving {
  transition: transform 480ms var(--lift-ease), box-shadow 400ms ease, opacity 320ms ease;
}

.item:focus-visible {
  outline: 2px solid var(--chalk);
  outline-offset: 4px;
}

.art {
  position: relative;
  display: block;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: #142b23;
}

.art img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
  user-select: none;
  -webkit-user-drag: none;
}

/* Film: vlakke poster met een lichte papierrand. */
.t-film .art { box-shadow: inset 0 0 0 1px rgba(236, 238, 232, .22); }

/* Boek: donkere rugband links, en een dikker voorwerp dus een zwaardere schaduw. */
.t-book {
  box-shadow:
    calc(var(--sx) * .3) calc(3px + 7px * var(--lift) + 5px * var(--zweef) + var(--sy) * .3)
      calc(6px + 9px * var(--lift) + 7px * var(--zweef)) rgba(0, 0, 0, calc(.42 + .04 * var(--lift) - .04 * var(--zweef))),
    var(--sx) calc(15px + 20px * var(--lift) + 16px * var(--zweef) + var(--sy))
      calc(28px + 26px * var(--lift) + 24px * var(--zweef)) rgba(0, 0, 0, calc(.36 + .08 * var(--lift) - .05 * var(--zweef)));
}
.t-book .art::after {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 6%;
  background: linear-gradient(90deg, rgba(0, 0, 0, .58), rgba(0, 0, 0, .06));
}

/* Game: een doosje met een dunne, lichte band bovenlangs en zachte hoeken. */
.t-game, .t-game .art { border-radius: 4px; }
.t-game .art { box-shadow: inset 0 0 0 1px rgba(236, 238, 232, .22); }
.t-game .art::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 5%;
  background: linear-gradient(180deg, rgba(236, 238, 232, .28), rgba(236, 238, 232, 0));
}

/* Gadget: een uitgeknipt voorwerp (png met doorzicht) dat los op het vilt ligt.
   Geen kaart, geen rand; de schaduw volgt de omtrek via drop-shadow op het beeld. */
.t-gadget, .t-gadget.is-lifted, .t-gadget.is-moving { box-shadow: none !important; background: none; }
.t-gadget .art { background: none; box-shadow: none; overflow: visible; }
.t-gadget .art img {
  object-fit: contain;
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, .45)) drop-shadow(0 12px 18px rgba(0, 0, 0, .35));
}
.t-gadget.is-lifted .art img { filter: drop-shadow(0 6px 8px rgba(0, 0, 0, .5)) drop-shadow(0 34px 50px rgba(0, 0, 0, .5)); }

/* Kunst: een schilderij in een smalle lijst, met een passe-partout van vilt erachter
   die net onder de rand uitkomt. De maat volgt het doek (3:4, 4:3, 16:9). */
.t-art .art {
  box-shadow:
    inset 0 0 0 3px #e6dfcc,
    inset 0 0 0 4px rgba(0, 0, 0, .35);
  background: #e6dfcc;
}
.t-art .art img { padding: 3px; box-sizing: border-box; }

/* Ding: een voorwerp van Wikidata. Vaak een foto met achtergrond, dus een kaart
   met een dunne rand; is het een uitgeknipte png, dan valt de rand weg. */
.t-ding .art { box-shadow: inset 0 0 0 1px rgba(236, 238, 232, .22); }

/* Sticker: een mens die is uitgeknipt met een witte rand ligt los op het vilt,
   zonder kaart, net als een gadget (Stefan, 9 sep: "maak van poppetjes stickers"). */
.item.is-sticker, .item.is-sticker.is-lifted, .item.is-sticker.is-moving { box-shadow: none !important; background: none; }
.item.is-sticker .art { background: none; box-shadow: none; overflow: visible; }
.item.is-sticker .art::after { display: none; }
.item.is-sticker .art img {
  object-fit: contain;
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, .4)) drop-shadow(0 10px 16px rgba(0, 0, 0, .3));
}
.item.is-sticker.is-lifted .art img { filter: drop-shadow(0 6px 8px rgba(0, 0, 0, .45)) drop-shadow(0 30px 44px rgba(0, 0, 0, .45)); }

/* Podcast: vierkante tegel met zachte hoeken. */
.t-podcast, .t-podcast .art { border-radius: 6px; }

/* Plaat en persoon: hoes met een dunne binnenrand. */
.t-music .art, .t-person .art { box-shadow: inset 0 0 0 2px rgba(236, 238, 232, .3); }

/* Video: schermpje met een donkere lijst en een krijtwit driehoekje. */
.t-video {
  padding: 6px;
  border-radius: 3px;
  background: #0b0e0c;
}
.t-video .art { border-radius: 1px; }
.play {
  position: absolute;
  right: 12px;
  bottom: 11px;
  width: 0;
  height: 0;
  border-left: 11px solid var(--chalk);
  border-top: 7px solid transparent;
  border-bottom: 7px solid transparent;
  opacity: .9;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, .7));
}

/* Link: kaartje. */
.t-link, .t-link .art { border-radius: 3px; }
.t-link .art { box-shadow: inset 0 0 0 1px rgba(236, 238, 232, .26); }

.item.is-drag { cursor: grabbing; }
.item.is-lifted { box-shadow: var(--sh-lift); cursor: zoom-out; z-index: 9000; }

.table.is-open .item:not(.is-lifted) { opacity: .35; pointer-events: none; }

/* Hartjes: het krijtplakkertje in de hoek rechtsonder, net over de rand heen
   zoals een sticker die je erop plakt. Het zit in de knop en niet in .art, want
   .art knipt af. De maat is vast in pixels: hij hangt aan het voorwerp, dus de
   camera schaalt hem net zo hard mee als de hoes eronder. */
.hartjes {
  position: absolute;
  right: 0;
  bottom: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 18px;
  padding: 0 6px;
  border: 1px solid rgba(236, 238, 232, .35);
  border-radius: 999px;
  background: rgba(11, 16, 13, .78);
  color: var(--chalk);
  font: 600 10px/1 var(--font-text);
  letter-spacing: -1px;
  white-space: nowrap;
  pointer-events: none;
  transform: translate(34%, 34%) rotate(-6deg);
  transition: opacity 200ms ease;
}

/* Opgetild staan de hartjes bij de titel in het paneel; op het voorwerp zelf
   zouden ze er dan twee keer staan. */
.item.is-lifted .hartjes { opacity: 0; }

/* Een gadget is een uitgeknipte png zonder kaart, dus de hoek rechtsonder van de
   knop is leeg vilt: daar plakt niets. Het krijtje gaat naar het midden van de
   onderrand van het beeld, want daar staat het voorwerp op de tafel. */
.t-gadget .hartjes {
  right: auto;
  left: 50%;
  transform: translate(-50%, 40%) rotate(-6deg);
}

/* Video: de knop heeft een lijst van 6px, dus het krijtje zou binnen het zwarte
   randje blijven hangen. Een tikje verder naar buiten en het hangt weer over de
   rand van het schermpje. */
.t-video .hartjes { transform: translate(42%, 42%) rotate(-6deg); }

/* ---------- hoeken van de tafel ---------- */

.label {
  position: absolute;
  left: var(--gap);
  top: clamp(14px, 2.4vw, 26px);
  z-index: 3;
  margin: 0;
  display: flex;
  align-items: baseline;
  gap: .5rem;
  flex-wrap: wrap;
  font-family: var(--font-display);
  font-size: 1.25rem;
  line-height: 1.2;
  font-weight: 400;
  pointer-events: none;
  text-shadow: 0 1px 3px rgba(11, 16, 13, .9), 0 0 16px rgba(11, 16, 13, .75);
}
.label-name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.25rem;
  letter-spacing: -.015em;
  color: var(--chalk);
}
.label-sub {
  font-family: var(--font-text);
  font-weight: 500;
  font-size: 1rem;
  color: var(--chalk-dim);
}

.hint {
  position: absolute;
  left: var(--gap);
  bottom: var(--bar);
  z-index: 3;
  margin: 0;
  max-width: 46vw;
  font-size: .95rem;
  color: var(--chalk-dim);
  pointer-events: none;
  text-shadow: 0 1px 3px rgba(11, 16, 13, .9), 0 0 16px rgba(11, 16, 13, .75);
  transition: opacity 320ms ease;
}
.hint[hidden] { display: none; }

/* Op een smal scherm past alleen de eerste zin, en die gaat boven de knoppenrij staan. */
@media (max-width: 680px) {
  .hint-2 { display: none; }
  .hint { max-width: 60vw; bottom: calc(var(--bar) + 54px); }
}

.knoppen {
  position: absolute;
  right: var(--gap);
  bottom: calc(var(--bar) + env(safe-area-inset-bottom, 0px));
  z-index: 3;
  display: flex;
  align-items: center;
  gap: 10px;
  transition: opacity 320ms ease;
}
.knoppen[hidden] { display: none; }

.knop {
  display: inline-flex;
  align-items: center;
  min-height: 48px;
  font: 500 1rem/1 var(--font-text);
  color: var(--chalk);
  background: rgba(11, 16, 13, .45);
  border: 1px solid rgba(236, 238, 232, .45);
  border-radius: 999px;
  padding: .65rem 1.2rem;
  cursor: pointer;
  transition: background-color 200ms ease, border-color 200ms ease;
}
.knop:hover { background: rgba(236, 238, 232, .12); border-color: var(--chalk); }
.knop:focus-visible { outline: 2px solid var(--chalk); outline-offset: 3px; }
.knop[hidden] { display: none; }

.table.is-open .hint,
.table.is-open .knoppen { opacity: 0; pointer-events: none; }

.empty {
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 3;
  transform: translate(-50%, -50%);
  margin: 0;
  padding: 0 24px;
  max-width: 22rem;
  text-align: center;
  font-size: 1.15rem;
  color: var(--chalk);
}

/* ---------- het paneel ---------- */

.panel {
  position: absolute;
  z-index: 5;
  display: flex;
  flex-direction: column;
  opacity: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  touch-action: pan-y;
  /* De tafel staat op user-select: none; hier mag het weer, want dit is tekst. */
  user-select: text;
  -webkit-user-select: text;
  -webkit-touch-callout: default;
  transition: opacity 300ms ease;
}
.panel.is-on { opacity: 1; }
.panel[hidden] { display: none; }

.panel-inner {
  width: 100%;
  max-width: 34rem;
  margin-block: auto;
  padding: 22px var(--gap) 30px;
  background: color-mix(in srgb, var(--felt) 38%, #0b100d);
  border-radius: 14px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, .35);
}

.panel-close {
  position: fixed;
  top: clamp(12px, 2.2vw, 24px);
  right: var(--gap);
  z-index: 6;
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  padding: 0;
  border: 1px solid rgba(236, 238, 232, .45);
  border-radius: 999px;
  background: rgba(11, 16, 13, .45);
  color: var(--chalk);
  font: 400 24px/1 var(--font-text);
  cursor: pointer;
  transition: background-color 200ms ease, border-color 200ms ease;
}
.panel-close:hover { background: rgba(236, 238, 232, .09); border-color: var(--chalk); }
.panel-close:focus-visible { outline: 2px solid var(--chalk); outline-offset: 3px; }

.panel-title {
  margin: 0 0 .3rem;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.5rem, 3vw, 2.25rem);
  line-height: 1.06;
  letter-spacing: -.02em;
  text-wrap: balance;
}
.panel-sub {
  margin: 0 0 1.15rem;
  font-size: 1rem;
  color: var(--chalk-dim);
}

/* De hartjes achter de titel in het paneel: krijt, en kleiner dan de naam zodat
   ze die niet overstemmen. */
.titel-hart {
  margin-left: .35em;
  font-family: var(--font-text);
  font-weight: 600;
  font-size: .58em;
  letter-spacing: -.04em;
  color: var(--chalk);
  vertical-align: .18em;
}
.panel-sub[hidden], .embed[hidden], .links[hidden] { display: none; }

/* "Verder bij 18:37": dezelfde stille regel als de ondertitel, met het knopje
   dat alsnog vanaf nul begint erachteraan. Hij staat onder de ondertitel en
   neemt diens marge over, zodat er geen extra gat valt als hij er niet is. */
.panel-verder {
  margin: 0 0 1.15rem;
  font-size: 1rem;
  color: var(--chalk-dim);
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: .5rem;
}
.panel-verder[hidden] { display: none; }
/* Staat er een ondertitel boven, dan hoort de regel daar tegenaan: samen een
   blokje over deze video, niet twee losse regels. */
.panel-sub:not([hidden]) + .panel-verder { margin-top: -.85rem; }
.verder-knop {
  font: 500 .82rem/1 var(--font-text);
  color: var(--chalk);
  background: none;
  border: 1px solid rgba(236, 238, 232, .4);
  border-radius: 999px;
  padding: .38rem .7rem;
  cursor: pointer;
  transition: background-color 200ms ease, border-color 200ms ease;
}
.verder-knop:hover { background: rgba(236, 238, 232, .12); border-color: var(--chalk); }
.verder-knop:focus-visible { outline: 2px solid var(--chalk); outline-offset: 3px; }
/* Een duim is geen muis: op een telefoon groeit het krijtje tot een echte knop,
   zonder dat de regel ernaast breder wordt. */
@media (max-width: 720px) {
  .verder-knop { min-height: 44px; padding-inline: .9rem; }
}

.postit {
  max-width: 25rem;
  margin: 0 0 1.3rem;
  padding: 1.05rem 1.2rem 1.25rem;
  background: var(--postit);
  color: var(--postit-ink);
  font-family: var(--font-text);
  font-weight: 500;
  font-size: 17px;
  line-height: 1.45;
  border-radius: 2px;
  transform: rotate(-1.5deg);
  box-shadow: 0 8px 18px rgba(0, 0, 0, .34);
}

/* Werk van een maker: een strook die zijwaarts schuift, elk stuk een link. */
.werk {
  display: flex;
  flex-wrap: wrap;
  gap: .6rem;
  margin: 0 0 1.25rem;
  max-width: 34rem;
}
.werk[hidden] { display: none; }
.werk-stuk {
  flex: 0 0 auto;
  display: block;
  width: calc(50% - .3rem);
  color: var(--chalk);
  text-decoration: none;
}
.werk-stuk img {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  background: #142b23;
  box-shadow: inset 0 0 0 1px rgba(236, 238, 232, .18), 0 6px 14px rgba(0, 0, 0, .35);
  transition: transform 220ms var(--lift-ease);
}
.werk-stuk:hover img, .werk-stuk:focus-visible img { transform: translateY(-2px) scale(1.02); }
.werk-stuk:focus-visible { outline: 2px solid var(--chalk); outline-offset: 3px; }
.werk-titel {
  display: block;
  margin-top: .3rem;
  font-size: .82rem;
  line-height: 1.25;
  color: var(--chalk-dim);
}
.werk-bron {
  flex-basis: 100%;
  margin: 0;
  font-size: .75rem;
  color: rgba(236, 238, 232, .45);
}
@media (min-width: 860px) {
  .werk-stuk { width: calc(33.333% - .4rem); }
}

.embed { margin: 0 0 1.25rem; max-width: 30rem; }
.embed-yt {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: 4px;
  background: #000;
}
.embed-yt iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.embed-sp { display: block; width: 100%; border: 0; border-radius: 12px; }

.links {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0 1.3rem;
}
.links a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--chalk);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
  text-decoration-color: rgba(236, 238, 232, .55);
}
.links a:hover { text-decoration-color: var(--chalk); }
.links a:focus-visible { outline: 2px solid var(--chalk); outline-offset: 3px; }

/* Telefoon: voorwerp bovenin, paneel eronder en scrollbaar. */
.panel { left: 0; right: 0; top: var(--panel-top); bottom: 0; }
.panel .panel-inner { margin-block: 0 auto; }

/* Breed is niet alleen een grote laptop. Een liggende telefoon van 844 bij 390
   heeft ook meer breedte dan hoogte, en die viel net buiten de grens van 860: het
   voorwerp stond bovenin en het paneel kreeg een strook van 187px onderaan,
   terwijl er 844px breedte naast lag. Dezelfde voorwaarde staat in stageOf() in
   app.js, anders kiezen de twee een andere indeling. */
@media (min-width: 860px), (min-aspect-ratio: 1/1) and (min-width: 700px) {
  .panel { left: 47%; right: 2%; top: 0; bottom: 0; }
  .panel .panel-inner { margin-block: auto; padding-top: 72px; padding-bottom: 40px; }
}

/* ---------- rust ---------- */

@media (prefers-reduced-motion: reduce) {
  .item, .item.is-moving, .panel, .panel-inner, .hint, .knoppen, .knop, .panel-close,
  .player { transition-duration: 120ms !important; }
}
.rust .item, .rust .item.is-moving, .rust .panel, .rust .panel-inner, .rust .hint,
.rust .player { transition-duration: 120ms !important; }

/* ---------- de speler: het opgetilde schermpje gaat zelf aan ---------- */

.player {
  position: absolute;
  z-index: 6;
  background: #0b0e0c;
  opacity: 0;
  transition: opacity 260ms ease;
}
.player.is-on { opacity: 1; }
.player[hidden] { display: none; }
.player iframe { display: block; width: 100%; height: 100%; border: 0; }

/* Van het glas naar het midden van het scherm en naar de hoek is telkens
   hetzelfde element dat van vak wisselt. De iframe blijft staan, dus het beeld
   loopt door; alleen zijn maten en zijn rand bewegen mee. */
.player.is-glij {
  transition: opacity 260ms ease,
    left 420ms var(--lift-ease), top 420ms var(--lift-ease),
    width 420ms var(--lift-ease), height 420ms var(--lift-ease),
    padding 420ms var(--lift-ease), transform 420ms var(--lift-ease);
}
/* Na een worp veert het venstertje naar de dichtstbijzijnde hoek. */
.player.is-veer {
  transition: opacity 260ms ease,
    left 380ms cubic-bezier(.2, .9, .25, 1.05), top 380ms cubic-bezier(.2, .9, .25, 1.05),
    width 380ms cubic-bezier(.2, .9, .25, 1.05), height 380ms cubic-bezier(.2, .9, .25, 1.05),
    padding 380ms cubic-bezier(.2, .9, .25, 1.05), transform 380ms cubic-bezier(.2, .9, .25, 1.05);
}
/* Tijdens het slepen schrijft JS elke stap een transform: daar hoort geen
   overgang bij, anders loopt het venstertje achter je vinger aan. */
.player.is-sleep { transition: opacity 260ms ease; }

/* Tijdens het slepen mag de iframe de aanwijzer niet afpakken: schuift de cursor
   door een haperend frame een tel over het beeld, dan verliest de pagina hem
   aan YouTube en blijft het venstertje aan de cursor hangen. Gemeten op 9 sep:
   omlaag slepen liep vast, omhoog niet. */
.player.is-sleep iframe { pointer-events: none; }
.player.is-sleep { user-select: none; -webkit-user-select: none; }
/* Losgemaakt: het venstertje hangt aan het scherm en speelt door. De rand van
   10px is meteen de greep, want een iframe slikt de aanwijzer zelf op. */
.player.is-los {
  position: fixed;
  z-index: 9500;
  border-radius: 2px;
  box-shadow: var(--sh-lift);
  touch-action: none;
  cursor: grab;
  user-select: none;
  -webkit-user-select: none;
}
.player.is-los.is-sleep { cursor: grabbing; }

.speler-balk { display: none; }
.player.is-los .speler-balk {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 100%;
  display: flex;
  align-items: center;
  gap: 8px;
  height: 44px;
  padding: 0 4px 0 12px;
  border-radius: 6px 6px 0 0;
  background: rgba(11, 16, 13, .88);
  color: var(--chalk);
  font: 400 13px/1 var(--font-text);
}
.speler-titel {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.speler-knop {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 36px;
  height: 36px;
  padding: 0 12px;
  border: 1px solid rgba(236, 238, 232, .4);
  border-radius: 999px;
  background: none;
  color: var(--chalk);
  font: 500 14px/1 var(--font-text);
  cursor: pointer;
}
.speler-knop:hover { border-color: var(--chalk); }
.speler-knop:focus-visible { outline: 2px solid var(--chalk); outline-offset: 2px; }
.speler-uit { padding: 0; width: 36px; font-size: 20px; }
/* Op een smal venstertje is er geen plek voor de titel naast twee knoppen. */
@media (max-width: 480px) {
  .player.is-los .speler-titel { display: none; }
  .player.is-los .speler-balk { justify-content: flex-end; }
}

/* Groter ligt rechtsboven op het glas, boven de iframe, en verdwijnt zodra de
   speler los of groot staat. */
.speler-groter {
  display: none;
  position: absolute;
  right: -10px;
  bottom: -14px;
  z-index: 2;
  height: 40px;
  padding: 0 16px;
  font-size: 14px;
  background: rgba(11, 16, 13, .92);
  border-color: rgba(236, 238, 232, .55);
  box-shadow: 0 4px 12px rgba(0, 0, 0, .4);
}
.player.is-on:not(.is-los) .speler-groter { display: inline-flex; }
.table.is-theater .speler-groter { display: none; }
.speler-groter:hover { background: rgba(11, 16, 13, .9); }

/* Groter: het beeld neemt het scherm over. Het schermpje en de tekst van het
   paneel gaan eronder weg; de sluitknop en de strook onderaan blijven. */
.panel-inner { transition: opacity 300ms ease, visibility 300ms ease; }
.table.is-theater .item.is-lifted { opacity: 0; }
.table.is-theater .panel-inner { opacity: 0; visibility: hidden; }
/* Het paneel gaat boven het beeld liggen zodat de sluitknop bereikbaar blijft,
   ook als het beeld tot in de bovenhoek komt. Alleen die knop vangt nog een
   aanwijzer: de rest van het scherm hoort bij de video. */
.table.is-theater .panel { z-index: 9450; pointer-events: none; }
.table.is-theater .panel-close { pointer-events: auto; }

.theater-balk {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 9400;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 10px var(--gap);
  padding-bottom: calc(10px + env(safe-area-inset-bottom, 0px));
  background: linear-gradient(to top, rgba(11, 16, 13, .92), rgba(11, 16, 13, 0));
}
.theater-titel {
  margin: 0;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font: 500 .95rem/1.2 var(--font-text);
  color: var(--chalk);
}

/* De veilige randen van het scherm staan alleen in CSS. Dit onzichtbare hulpje
   zet ze als padding, zodat app.js ze kan opmeten voor de hoeken. */
.veilig-hulp {
  position: absolute;
  left: 0;
  top: 0;
  width: 0;
  height: 0;
  visibility: hidden;
  pointer-events: none;
  padding: env(safe-area-inset-top, 0px) env(safe-area-inset-right, 0px)
    env(safe-area-inset-bottom, 0px) env(safe-area-inset-left, 0px);
}

/* ---------- cover kwijt: viltkaartje met de titel ---------- */

.art-title {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 8%;
  text-align: center;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(.7rem, 1.1vw, .95rem);
  line-height: 1.15;
  color: var(--chalk);
  background: #163329;
  box-shadow: inset 0 0 0 2px rgba(236, 238, 232, .18);
  overflow-wrap: normal;
}

.postit[hidden] { display: none; }

/* ---------- verwant voorwerp: knop in de linkslijst ---------- */

.links .verwant {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  margin: 0;
  padding: 0 14px;
  border: 1.5px solid var(--chalk-dim);
  border-radius: 999px;
  background: none;
  color: var(--chalk);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}
.links .verwant:hover { border-color: var(--chalk); }
.links .verwant:focus-visible { outline: 2px solid var(--chalk); outline-offset: 3px; }

.embed-ap, .embed-dz {
  display: block;
  width: 100%;
  max-width: 660px;
  border: 0;
  border-radius: 12px;
  overflow: hidden;
  background: transparent;
}


/* ==========================================================================
   Sfeer: losse schakelaars, alleen zichtbaar met ?sfeer=1. Staat alles uit,
   dan is dit blok dood gewicht en is de tafel precies de gewone tafel.
   ========================================================================== */

.sfeer {
  position: absolute;
  right: var(--gap);
  top: clamp(14px, 2.4vw, 26px);
  z-index: 7;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: .45rem;
  max-width: min(28rem, 52vw);
  transition: opacity 200ms ease;
}
.sfeer[hidden] { display: none; }
.table.is-open .sfeer { opacity: 0; pointer-events: none; }

.sfeer-kop {
  margin: 0;
  font: 500 .8rem/1 var(--font-text);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: rgba(236, 238, 232, .5);
}
.sfeer-rij {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: .4rem;
}

.chip {
  display: inline-flex;
  align-items: center;
  min-height: 32px;
  padding: .3rem .7rem;
  font: 500 .85rem/1 var(--font-text);
  color: rgba(236, 238, 232, .78);
  background: rgba(11, 16, 13, .5);
  border: 1px solid rgba(236, 238, 232, .3);
  border-radius: 999px;
  cursor: pointer;
  transition: background-color 160ms ease, border-color 160ms ease, color 160ms ease;
}
.chip:hover { border-color: rgba(236, 238, 232, .7); color: var(--chalk); }
.chip:focus-visible { outline: 2px solid var(--chalk); outline-offset: 3px; }
.chip[aria-pressed="true"] {
  color: var(--ink);
  background: var(--chalk);
  border-color: var(--chalk);
}

/* 1. Scherptediepte: twee standen: scherp of 1 px waas. */
.item.dof-1 { filter: blur(1px); }



@media (max-width: 720px) {
  .sfeer { max-width: 62vw; gap: .3rem; }
  .chip { min-height: 28px; padding: .22rem .5rem; font-size: .74rem; }
}
.chip[disabled] { opacity: .4; cursor: default; }
/* ==========================================================================
   Filter op soort: krijtjes langs de onderrand. Klikken haalt alles wat niet
   gekozen is van tafel en legt de rest opnieuw; Alles gooit de hele tafel terug
   op de plek waar hij lag.
   ========================================================================== */

.filters {
  position: absolute;
  left: var(--gap);
  bottom: var(--bar);
  z-index: 3;
  max-width: calc(100% - var(--gap) * 2 - 260px);
  transition: opacity 320ms ease;
}
.filters[hidden] { display: none; }
.table.is-open .filters { opacity: 0; pointer-events: none; }

.filter-rij {
  display: flex;
  flex-wrap: wrap;
  gap: .35rem;
}

/* Krapper dan de sfeerkrijtjes: er staan er tien naast elkaar en ze moeten op
   een laptop op een regel passen naast de knoppenrij. */
.filters .chip { min-height: 34px; padding: .3rem .58rem; }

/* Het krijtje Hartjes draagt een hartje in plaats van een woord; het woord staat
   in het aria-label. Iets groter dan de namen ernaast, anders verdwijnt het, en
   verder krapper: een teken heeft minder lucht nodig dan een woord, en de rij
   hoort op een laptop van 1280 nog op een regel te passen. */
.filters .chip-hart { padding-inline: .38rem; }
.chip-hart .filter-naam {
  font-size: 1rem;
  line-height: 1;
}
.chip-hart .filter-aantal { margin-left: .28rem; }

/* Het aantal hoort bij de naam, maar mag hem niet overstemmen. */
.filter-aantal {
  margin-left: .35rem;
  font-size: .78rem;
  font-variant-numeric: tabular-nums;
  color: rgba(236, 238, 232, .45);
}
.chip:hover .filter-aantal { color: rgba(236, 238, 232, .7); }
.chip[aria-pressed="true"] .filter-aantal { color: rgba(15, 20, 17, .5); }

/* Op een telefoon en een tablet past de rij niet naast de knoppen: dan gaat hij
   er als een schuifbare regel bovenop staan. Elf krijtjes zijn ruim 900px. */
@media (max-width: 1080px) {
  .filters {
    left: 0;
    right: 0;
    bottom: calc(var(--bar) + 52px);
    max-width: none;
    padding-inline: var(--gap);
    overflow-x: auto;
    scrollbar-width: none;
  }
  .filters::-webkit-scrollbar { display: none; }
  .filter-rij { flex-wrap: nowrap; }
  /* Een duim is geen muis: hier zijn dit de knoppen die je het meest raakt. */
  .filters .chip { min-height: 44px; padding: .3rem .8rem; font-size: .85rem; }
}

/* ---------- taal en 3D in de knoppenrij ---------- */

.knop-taal, .naar3d {
  padding-inline: .95rem;
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: .02em;
}


/* De geluidsknop: hetzelfde krijtje als Schud, maar smal. */
.knop-geluid { padding-inline: .8rem; font-size: 1.05rem; line-height: 1; }
.knop-geluid.is-uit { color: rgba(236, 238, 232, .45); border-color: rgba(236, 238, 232, .25); }

/* ---------- viltbanden achter het label en de knoppenrij, zodat die leesbaar blijven
   nu de stapel onder de randen door kan schuiven ---------- */

.table::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background:
    linear-gradient(to top, color-mix(in srgb, var(--felt) 92%, transparent) 0, color-mix(in srgb, var(--felt) 55%, transparent) 64px, transparent 130px);
}
.table.is-open::before { opacity: 0; }

.sfeer-meter {
  margin: .1rem 0 0;
  font: 500 .78rem/1.2 var(--font-text);
  color: rgba(236, 238, 232, .6);
}

/* Tijdens de zoom staan de schaduwen even uit: op elke tussenschaal opnieuw
   rasteren kost meer dan het oplevert, en zien doe je ze dan toch niet. */
.items.is-zoomend .item { box-shadow: none; }

/* De deelafbeelding (og.jpg) is de tafel zelf, zonder knoppen en krijtjes. */
html.og .knoppen, html.og .filters, html.og .sfeer, html.og .kleur, html.og .spoor { display: none !important; }

/* Alleen voor schermlezers en de kop-structuur: het label staat niet meer in beeld
   (Stefan, 9 sep: "keep it stupid simple"). */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ---------- de kleurkiezer: één rond knopje linksonder, de kleur van het vilt ---------- */

.kleur {
  position: absolute;
  left: var(--gap);
  bottom: calc(var(--bar) + env(safe-area-inset-bottom, 0px));
  z-index: 3;
  display: flex;
  align-items: center;
  gap: 8px;
  transition: opacity 320ms ease;
}
.table.is-open .kleur { opacity: 0; pointer-events: none; }
.kleur-knop, .kleur-vak {
  width: 34px;
  height: 34px;
  padding: 0;
  border: 2px solid rgba(236, 238, 232, .7);
  border-radius: 999px;
  background: var(--felt);
  box-shadow: 0 2px 6px rgba(0, 0, 0, .35);
  cursor: pointer;
  transition: transform 200ms var(--lift-ease), border-color 200ms ease;
}
/* Het knopje zelf laat zien dat het over kleur gaat: een ring van kleur om het
   vilt van nu (de oma-lens: "een kale cirkel in de kleur van het vilt"). */
.kleur-knop {
  position: relative;
  width: 46px;
  height: 46px;
  background: conic-gradient(#c94f4f, #d99a3c, #c9c24a, #5aa86c, #4a7fd4, #8a63c9, #c94f4f);
}
.kleur-knop::after {
  content: "";
  position: absolute;
  inset: 5px;
  border-radius: 999px;
  background: var(--felt);
  box-shadow: inset 0 0 0 1px rgba(236, 238, 232, .35);
}
.kleur-knop:hover, .kleur-vak:hover { transform: scale(1.08); border-color: var(--chalk); }
.kleur-knop:focus-visible, .kleur-vak:focus-visible { outline: 2px solid var(--chalk); outline-offset: 3px; }
.kleur-knop[aria-expanded="true"] { border-color: var(--chalk); }
.kleur-rij {
  display: flex;
  align-items: center;
  gap: 8px;
}
.kleur-rij[hidden] { display: none; }
.kleur-vak { width: 36px; height: 36px; }
.kleur-vak[aria-pressed="true"] { border-color: var(--chalk); box-shadow: 0 0 0 2px var(--felt), 0 0 0 4px var(--chalk); }
/* Het laatste vak is de vrije kiezer: een regenboog met het kleurveld van de browser erin. */
.kleur-vrij {
  position: relative;
  overflow: hidden;
  background: conic-gradient(#e5484d, #f5a524, #e2d21a, #35c26b, #2f8ff5, #8b5cf6, #e5484d);
}
.kleur-vrij input {
  position: absolute;
  inset: -8px;
  width: 200%;
  height: 200%;
  padding: 0;
  border: 0;
  opacity: 0;
  cursor: pointer;
}
/* Op een telefoon past de rij niet naast het knopje. Gemeten op 390 breed: de rij
   was 328px, met het knopje erbij liep het blok tot x=398 op een scherm van 390 en
   lag hij over "about me" heen; op 375 stak hij er 23px buiten. Onder 720px klapt
   hij daarom omhoog uit het knopje in plaats van ernaast: een kolom vakjes van
   40px die van onderen naar boven opkomt. De kolom staat los uit de stroom, dus
   het blok blijft zo breed als het knopje zelf en kan niets meer raken. Past hij
   niet in de hoogte, dan wijkt hij uit naar een tweede kolom ernaast. */
@media (max-width: 720px) {
  .kleur { align-items: flex-end; }
  .kleur-rij {
    position: absolute;
    left: 0;
    bottom: calc(100% + 10px);
    flex-flow: column-reverse wrap;
    align-items: flex-start;
    gap: 10px;
    /* Boven blijft ruimte vrij voor de spoorpijltjes linksboven. */
    max-height: calc(100dvh - var(--bar) - env(safe-area-inset-bottom, 0px) - 130px);
  }
  .kleur-vak { width: 40px; height: 40px; }
  /* De vakjes komen van onder naar boven op, het dichtst bij de duim het eerst. */
  .kleur-rij:not([hidden]) > * { animation: kleur-op 240ms var(--lift-ease) backwards; }
  .kleur-rij > *:nth-child(2) { animation-delay: 30ms; }
  .kleur-rij > *:nth-child(3) { animation-delay: 60ms; }
  .kleur-rij > *:nth-child(4) { animation-delay: 90ms; }
  .kleur-rij > *:nth-child(5) { animation-delay: 120ms; }
  .kleur-rij > *:nth-child(6) { animation-delay: 150ms; }
  .kleur-rij > *:nth-child(7) { animation-delay: 180ms; }
}
@keyframes kleur-op {
  from { opacity: 0; transform: translateY(14px) scale(.72); }
  to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .kleur-rij > * { animation: none !important; }
}
.rust .kleur-rij > * { animation: none !important; }

/* ---------- het spoor: vorige en volgende, linksboven, heel stil ----------
   Per ongeluk weggeklikt is één tik terug; en je kunt door wat je al opende
   heen en weer lopen zonder de tafel af te zoeken. */
.spoor {
  position: absolute;
  left: var(--gap);
  top: clamp(12px, 2.2vw, 24px);
  z-index: 7;
  display: flex;
  gap: 6px;
  opacity: .55;
  transition: opacity 240ms ease;
}
.spoor:hover, .spoor:focus-within { opacity: 1; }
.spoor[hidden] { display: none; }
.spoor-knop {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid rgba(236, 238, 232, .4);
  border-radius: 999px;
  background: rgba(11, 16, 13, .45);
  color: var(--chalk);
  font: 400 26px/1 var(--font-text);
  cursor: pointer;
  transition: background-color 200ms ease, border-color 200ms ease, opacity 200ms ease;
}
.spoor-knop:hover { background: rgba(236, 238, 232, .12); border-color: var(--chalk); }
.spoor-knop:focus-visible { outline: 2px solid var(--chalk); outline-offset: 3px; }
.spoor-knop[disabled] { opacity: .3; cursor: default; }
