/* Signed-in area — Bootstrap in dark mode, dressed in the Straovers palette.
   Loaded after vendor/bootstrap.min.css, so these rules win.
   Tokens come from colors_and_type.css. */

:root,
[data-bs-theme="dark"] {
  --bs-body-bg: var(--earth-deep);
  --bs-body-color: var(--parchment-dim);
  --bs-emphasis-color: var(--parchment);
  --bs-border-color: rgba(var(--creme-rgb), 0.12);
  --bs-primary: var(--gold-muted);
  --bs-primary-rgb: var(--goud-rgb);
  --bs-link-color: var(--gold-muted);
  --bs-link-color-rgb: var(--goud-rgb);
  --bs-link-hover-color: var(--parchment);
  --bs-secondary-color: var(--fog-light);
  --bs-tertiary-bg: var(--earth-warm);
  --bs-body-font-family: var(--font-meta);
  --bs-focus-ring-color: rgba(var(--goud-rgb), 0.35);
}

body {
  background: var(--earth-deep);
  min-height: 100vh;
}

/* ===== Navbar ===== */
.app-navbar {
  background: rgba(var(--grond-diep-rgb), 0.92);
  backdrop-filter: blur(14px) saturate(115%);
  -webkit-backdrop-filter: blur(14px) saturate(115%);
  border-bottom: 1px solid rgba(var(--creme-rgb), 0.08);
}
.app-navbar .navbar-brand {
  font-family: var(--font-display);
  font-size: 1.35rem;
  letter-spacing: 0.01em;
  color: var(--parchment);
}
.app-navbar .nav-link {
  font-size: 0.875rem;
  letter-spacing: 0.06em;
  color: var(--parchment-dim);
}
.app-navbar .nav-link:hover,
.app-navbar .nav-link.active { color: var(--gold-muted); }

.app-usermenu {
  background: none;
  border: 0;
  color: var(--parchment-dim);
  font-size: 0.875rem;
  letter-spacing: 0.06em;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0;
}
.app-usermenu:hover { color: var(--gold-muted); }
.app-usermenu-avatar {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  object-fit: cover;
  border: 1px solid rgba(var(--creme-rgb), 0.16);
}
.app-usermenu-initials {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--earth-mid);
  border: 1px solid rgba(var(--creme-rgb), 0.16);
  color: var(--parchment);
  font-size: 0.75rem;
  letter-spacing: 0.04em;
}
.app-dropdown {
  position: absolute;
  right: 0;
  top: calc(100% + 8px);
  min-width: 220px;
  background: var(--earth-warm);
  border: 1px solid rgba(var(--creme-rgb), 0.12);
  border-radius: 4px;
  box-shadow: var(--shadow-image);
  padding: 0.5rem 0;
  z-index: 1030;
}
.app-dropdown a,
.app-dropdown button {
  display: block;
  width: 100%;
  text-align: left;
  padding: 0.5rem 1rem;
  font-size: 0.875rem;
  color: var(--parchment-dim);
  text-decoration: none;
  background: none;
  border: 0;
}
.app-dropdown a:hover,
.app-dropdown button:hover { background: var(--earth-mid); color: var(--parchment); }
.app-dropdown-header {
  padding: 0.35rem 1rem 0.6rem;
  font-size: 0.75rem;
  color: var(--fog-grey);
  border-bottom: 1px solid rgba(var(--creme-rgb), 0.08);
  margin-bottom: 0.4rem;
}

/* ===== Surfaces ===== */
.card {
  --bs-card-bg: var(--earth-warm);
  --bs-card-border-color: rgba(var(--creme-rgb), 0.1);
  --bs-card-cap-bg: rgba(var(--creme-rgb), 0.03);
}
.list-group {
  --bs-list-group-bg: var(--earth-warm);
  --bs-list-group-border-color: rgba(var(--creme-rgb), 0.1);
  --bs-list-group-color: var(--parchment-dim);
  --bs-list-group-action-hover-bg: var(--earth-mid);
  --bs-list-group-action-hover-color: var(--parchment);
}
.table { --bs-table-color: var(--parchment-dim); --bs-table-border-color: rgba(var(--creme-rgb), 0.1); }
.form-control, .form-select {
  background: rgba(var(--creme-rgb), 0.04);
  border-color: var(--border-field);
  color: var(--parchment);
}
.form-control:focus, .form-select:focus {
  background: rgba(var(--creme-rgb), 0.06);
  border-color: var(--gold-muted);
  color: var(--parchment);
  box-shadow: 0 0 0 0.2rem rgba(var(--goud-rgb), 0.15);
}
.form-control::placeholder { color: rgba(var(--creme-rgb), 0.4); }

.btn-primary {
  --bs-btn-bg: var(--gold-muted);
  --bs-btn-border-color: var(--gold-muted);
  --bs-btn-color: var(--earth-deep);
  --bs-btn-hover-bg: var(--parchment-deep);
  --bs-btn-hover-border-color: var(--parchment-deep);
  --bs-btn-hover-color: var(--earth-deep);
  --bs-btn-active-bg: var(--gold-low);
  --bs-btn-active-border-color: var(--gold-low);
  --bs-btn-disabled-bg: var(--gold-low);
  --bs-btn-disabled-border-color: var(--gold-low);
  --bs-btn-disabled-color: var(--earth-deep);
  font-weight: 500;
}
.btn-outline-secondary {
  --bs-btn-color: var(--parchment-dim);
  --bs-btn-border-color: rgba(var(--creme-rgb), 0.25);
  --bs-btn-hover-bg: var(--earth-mid);
  --bs-btn-hover-border-color: var(--gold-muted);
  --bs-btn-hover-color: var(--parchment);
}

/* ===== Tooltip =====
   Zonder JavaScript. De `title` van de browser wacht een seconde, is niet te
   vormgeven en verschijnt waar de muis is in plaats van bij de knop; Bootstrap's
   eigen tooltip zou hun JS én Popper binnenhalen, en die laden we hier bewust niet.
   Alleen op apparaten met een muis: op een aanraakscherm bestaat zweven niet, en
   dan zou de tekst blijven hangen na een tik. */
@media (hover: hover) {
  [data-tooltip] { position: relative; }
  [data-tooltip]::after {
    content: attr(data-tooltip);
    position: absolute;
    bottom: calc(100% + 7px);
    left: 50%;
    translate: -50% 0;
    z-index: 1050;
    padding: 0.3rem 0.55rem;
    border-radius: 4px;
    background: var(--earth-deep);
    border: 1px solid rgba(var(--creme-rgb), 0.16);
    color: var(--parchment);
    font-size: 0.75rem;
    line-height: 1.3;
    white-space: nowrap;
    opacity: 0;
    pointer-events: none;
    transition: opacity 120ms var(--ease-fade);
  }
  /* :focus-visible en niet :focus — anders springt hij ook aan na een muisklik. */
  [data-tooltip]:hover::after,
  [data-tooltip]:focus-visible::after { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  [data-tooltip]::after { transition: none; }
}

/* ===== Page furniture ===== */
.app-title {
  font-family: var(--font-display);
  font-weight: 400;
  letter-spacing: -0.01em;
  color: var(--parchment);
}
.app-eyebrow {
  font-size: 0.7rem;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--fog-grey);
}
.app-muted { color: var(--fog-grey); }

/* Auth screens: a single centred card. */
.app-auth {
  min-height: calc(100vh - 64px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 3rem 1rem;
}
.app-auth-card { width: 100%; max-width: 420px; }
.app-auth-brand {
  font-family: var(--font-display);
  font-size: 2rem;
  color: var(--parchment);
  text-align: center;
  margin-bottom: 0.25rem;
}
.app-auth-sub {
  font-family: var(--font-body);
  font-style: italic;
  color: var(--fog-grey);
  text-align: center;
  margin-bottom: 2rem;
}

/* Bootstrap's warning yellow is far too loud against this palette. */
.badge-role {
  background: rgba(var(--goud-rgb), 0.15);
  border: 1px solid rgba(var(--goud-rgb), 0.4);
  color: var(--gold-muted);
  font-weight: 500;
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  padding: 0.25em 0.6em;
  border-radius: 3px;
}

/* ===== Album ===== */
.album-cover {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  display: block;
}
.album-cover--empty {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--earth-mid);
  color: rgba(var(--creme-rgb), 0.35);
  font-family: var(--font-display);
  font-size: 3rem;
}

/* ===== Albumkop ===== */
/* De hoes wordt zo hoog als de tekst ernaast: geen vaste maat, want dan staat er
   boven de titel lucht die nergens over gaat. De breedte volgt uit de hoogte — het
   is een vierkant — en de hoogte uit de tekst, doordat de afbeelding er los in
   hangt en dus zelf niets aan de rij bijdraagt. */
.album-head { display: flex; align-items: stretch; gap: 1.5rem; }
.album-head__cover {
  flex: none;
  position: relative;
  aspect-ratio: 1;
  min-height: 9rem;
  cursor: zoom-in;
}
.album-head__cover .album-cover { position: absolute; inset: 0; width: 100%; height: 100%; }
.album-head__body { flex: 1 1 auto; min-width: 0; }
/* Op een telefoon onder elkaar, en dan eerst waar je naar kijkt: de naam van de
   plaat. De hoes komt eronder. */
@media (max-width: 575.98px) {
  .album-head { flex-direction: column; align-items: stretch; }
  .album-head__cover { order: 2; width: 60vw; max-width: 15rem; position: static; }
  .album-head__cover .album-cover { position: static; }
}

/* ===== Album: de lijst links, het nummer rechts ===== */
/* Dezelfde opzet als de dashboardpanelen: een vaste kolom naast een kolom die de rest
   vult. Onder deze breedte is er geen zijkolom maar een paneel dat omhoog schuift. */
.album-layout { --album-side: 22rem; }
@media (min-width: 1200px) {
  .album-layout { display: flex; align-items: flex-start; gap: 2rem; }
  .album-layout__main { flex: 1 1 auto; min-width: 0; }
  /* De navigatiebalk plakt zelf ook, dus hieronder beginnen. De kolom loopt door tot
     onder de spelerbalk en scrollt in zichzelf; de ruimte onderin zorgt dat het
     laatste kaartje boven die balk uit te scrollen is. */
  .album-side {
    flex: 0 0 var(--album-side);
    position: sticky;
    top: 5rem;
    max-height: calc(100vh - 5rem);
    overflow-y: auto;
    padding-bottom: 7rem;
    scrollbar-width: thin;
  }
}
/* Bovenin staat het nummer zelf, los in de kolom; wat je erbij kunt opzoeken zit in
   kaartjes eronder. */
.album-side__panel { display: flex; flex-direction: column; gap: 1rem; }
.album-side__panel[hidden] { display: none; }
.album-side__panel > * { margin-bottom: 0; }
.album-side__card {
  background: var(--earth-warm);
  border: 1px solid rgba(var(--creme-rgb), 0.1);
  border-radius: 4px;
  padding: 1rem 1.25rem;
}
.album-side__album {
  align-self: flex-start;
  border: 0;
  background: none;
  padding: 0;
  font-family: var(--font-meta);
  font-size: 0.7rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--fog-grey);
}
.album-side__album:hover { color: var(--gold-muted); }
.album-side__artwork { width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: 3px; display: block; }
.album-side__bar { display: none; }
.album-side__close {
  margin-left: auto;
  border: 0;
  background: none;
  color: var(--parchment-dim);
  font-size: 1.6rem;
  line-height: 1;
  padding: 0 0.25rem;
}
.album-side__close:hover { color: var(--gold-muted); }

/* Op een smal scherm vult diezelfde kolom het scherm: een smalle balk met de
   sluitknop bovenaan, de inhoud daartussen, en de speler onderin. Die laatste ligt
   hoger in de stapeling (1020), dus hij blijft gewoon zichtbaar en bedienbaar —
   vandaar de ruimte onder de inhoud, zodat je er niet achter vast komt te zitten. */
@media (max-width: 1199.98px) {
  .album-side {
    position: fixed;
    inset: 0;
    z-index: 1030;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    background: var(--earth-deep);
    transform: translateY(100%);
    transition: transform 280ms var(--ease-fade);
  }
  .album-side--open { transform: translateY(0); }
  .album-side__bar {
    display: flex;
    align-items: center;
    flex: none;
    padding: 0.5rem 1rem;
    border-bottom: 1px solid rgba(var(--creme-rgb), 0.12);
  }
  .album-side__body {
    flex: 1 1 auto;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 1rem 1rem 10rem;
  }
  /* Het gaat hier om de woorden; de afbeelding mag niet het halve scherm opeten
     voordat je iets gelezen hebt. */
  .album-side__artwork { width: auto; max-width: 100%; max-height: 30vh; margin-inline: auto; }

}

/* ===== De songtekst als laag =====
   Op elk schermformaat hetzelfde: de tekst komt over de pagina en de lijst blijft
   erachter staan, vervaagd. Eerder nam de tekst op een breed scherm de plaats van de
   lijst in, en dan verdwijnt waar je was. z-index 1030, dus onder de speler (1040):
   lezen en doorspoelen tegelijk moet kunnen. */
.album-lyrics:not([hidden]) {
  position: fixed;
  inset: 0;
  z-index: 1030;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  margin: 0;
  background: rgba(var(--grond-diep-rgb), 0.72);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.album-lyrics__sheet {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
  background: var(--earth-deep);
}
.album-lyrics__bar {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  flex: none;
  padding: 0.5rem 1rem;
  border-bottom: 1px solid rgba(var(--creme-rgb), 0.12);
}
/* Ruimte onderaan, anders komen de laatste regels achter de speler vast te zitten. */
.album-lyrics__body {
  flex: 1 1 auto;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 1rem 1rem 10rem;
}

/* Op een breed scherm geen schermvullend vlak maar een venster in het midden: zo
   zie je dat de lijst er nog is en dat dit iets is dat je weer kunt sluiten. */
@media (min-width: 1200px) {
  .album-lyrics:not([hidden]) {
    align-items: center;
    justify-content: center;
    padding: 3rem 1.5rem 9rem;
  }
  .album-lyrics__sheet {
    flex: 0 1 auto;
    width: min(44rem, 100%);
    max-height: 100%;
    border: 1px solid rgba(var(--creme-rgb), 0.14);
    border-radius: 8px;
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.5);
  }
  .album-lyrics__body { padding: 1.25rem 1.5rem 2rem; }
}

/* De songtekst neemt de plaats van de lijst in. Verbergen met het attribuut, dus de
   regels blijven in de pagina staan en de speler kan er gewoon doorheen stappen. */
.album-tracks[hidden], .album-lyrics[hidden], .album-lyrics__body > [hidden] { display: none; }

/* ===== Verhalen als regels, voor in de zijkolom ===== */
.story-links > h3 { margin-bottom: 0.5rem; }
.story-link {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.35rem 0;
  text-decoration: none;
}
.story-link__thumb { width: 3rem; height: 3rem; object-fit: cover; border-radius: 3px; flex: none; }
.story-link__body { min-width: 0; }
.story-link__title {
  display: block;
  font-family: var(--font-display);
  font-size: 0.95rem;
  color: var(--parchment);
}
.story-link:hover .story-link__title { color: var(--gold-muted); }
.story-link__date { display: block; font-size: 0.7rem; color: var(--fog-grey); }

/* De twee knoppen onder de albumtitel. De knop toont wat hij dóet, niet wat er
   speelt: een driehoek als er niets klinkt, twee streepjes als dat wel zo is. */
.album-head__actions { display: flex; flex-wrap: wrap; gap: 0.6rem; }
.album-head__actions .btn { display: inline-flex; align-items: center; gap: 0.5rem; }
.album-head__icon { display: inline-flex; line-height: 0; }
.album-head__icon--pause { display: none; gap: 3px; align-items: center; height: 14px; }
.album-head__icon--pause span { width: 4px; height: 100%; background: currentColor; border-radius: 1px; }
.album-head__play.is-playing .album-head__icon--play { display: none; }
.album-head__play.is-playing .album-head__icon--pause { display: inline-flex; }

/* ===== Track list =====
   Geen kaart per nummer en geen rondje om het cijfer: op een lijst van negen tracks
   telde dat op tot negen omlijnde vlakken met negen omlijnde bollen erin, en dan
   vraagt de vormgeving meer aandacht dan de muziek. Wat overblijft is een regel die
   oplicht als je erover gaat. */
.track {
  padding: 0.45rem 0.6rem;
  border-radius: 5px;
  transition: background var(--dur-fast) var(--ease-fade);
}
.track--playable { cursor: pointer; }
/* Het geladen nummer blijft opgelicht, ook als het gepauzeerd staat. */
.track--current { background: rgba(var(--creme-rgb), 0.05); }
.track--playable:hover { background: rgba(var(--creme-rgb), 0.08); }
.track--current .track__title { color: var(--gold-muted); }
/* Nummer, pictogram en balkjes liggen alle drie in hetzelfde vakje, dus wat er ook
   staat, het staat op dezelfde plek en de titels blijven uitgelijnd. */
.track__play {
  width: 2rem;
  height: 2rem;
  flex: 0 0 2rem;
  /* Zonder eigen rand komt de standaardopmaak van de browser tevoorschijn: een
     knop krijgt vanzelf een randje en een vlakje. */
  background: none;
  border: 0;
  padding: 0;
  color: var(--parchment-dim);
  display: grid;
  place-items: center;
  transition: color 200ms var(--ease-fade);
}
.track__play > * { grid-area: 1 / 1; }
.track--playable:hover .track__play { color: var(--parchment); }
/* A track without audio keeps the slot, so every row lines up. */
.track__play--silent { opacity: 0.55; }
.track__number { font-size: 0.85rem; font-variant-numeric: tabular-nums; color: var(--fog-grey); }
.track__icon, .track__bars { display: none; }
.track__icon { line-height: 0; }
.track__icon--pause { gap: 3px; align-items: center; height: 13px; }
.track__icon--pause span { width: 4px; height: 100%; background: currentColor; border-radius: 1px; }

/* Wat er in het rondje staat, per stand. Elke stand sluit de andere uit in de
   selector zelf en niet in de volgorde: :hover telt mee in de specificiteit, dus een
   hover-regel wint anders van een latere regel die hem juist moest overrulen. */
.track--playable:hover .track__number,
.track--current .track__number { display: none; }

.track--playable:not(.track--playing):hover .track__icon--play,
.track--current:not(.track--playing) .track__icon--play { display: block; }

.track--playing:not(:hover) .track__bars { display: flex; }
.track--playing:hover .track__icon--pause { display: flex; }
.track--current .track__play { color: var(--gold-muted); }

/* Het nummer speelt: vier balkjes die meebewegen, zoals op een versterker. */
.track__bars { gap: 2px; align-items: flex-end; height: 13px; }
.track__bars span {
  width: 3px;
  height: 100%;
  background: currentColor;
  transform-origin: bottom;
  animation: track-bars 1s var(--ease-fade) infinite;
}
.track__bars span:nth-child(2) { animation-delay: -0.75s; }
.track__bars span:nth-child(3) { animation-delay: -0.35s; }
.track__bars span:nth-child(4) { animation-delay: -0.55s; }
@keyframes track-bars {
  0%, 100% { transform: scaleY(0.25); }
  50% { transform: scaleY(1); }
}
@media (prefers-reduced-motion: reduce) {
  .track__bars span { animation: none; transform: scaleY(0.55); }
}
.track__title { color: var(--parchment); flex: 1 1 auto; min-width: 0; }
.track__duration { flex: none; font-variant-numeric: tabular-nums; }
/* De knoppen achteraan staan in een vakje van vaste breedte, ook als er niets in
   zit: anders schuift de duur van een nummer zonder audio of zonder tekst uit de
   kolom en staat de lijst scheef. */
.track__actions { flex: 0 0 4.5rem; display: flex; justify-content: flex-end; gap: 0.35rem; }
.track__credits {
  font-size: 0.75rem;
  color: var(--fog-grey);
  margin-top: 2px;
}

/* ===== Player, pinned to the bottom of the window ===== */
.player {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  /* Boven de navigatiebalk (1020) én boven het schermvullende paneel (1030): waar je
     ook bent, de muziek blijft bedienbaar. */
  z-index: 1040;
  background: rgba(var(--grond-diep-rgb), 0.94);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-top: 1px solid rgba(var(--creme-rgb), 0.1);
  padding: 0.75rem 0;
}
/* Ruimte voor de speler, zodat die nooit het laatste van de pagina afdekt. Met
   !important, want de py-4 van Bootstrap op <main> draagt dat zelf ook en wint
   anders ongeacht hoe specifiek wij worden. */
body:has(.player:not([hidden])) main { padding-bottom: 8rem !important; }
/* Op de albumpagina zit die ruimte in de kolom met de tracklijst. De zijkolom plakt
   binnen de indeling en blijft staan tot de ónderkant daarvan; alles wat daarbuiten
   valt — padding van <main>, of van de indeling zelf, want die telt niet mee — is
   ruimte waarin hij alsnog mee omhoog schuift en van boven wordt afgekapt. */
body:has(.player:not([hidden])) main:has(.album-layout) { padding-bottom: 0 !important; }
body:has(.player:not([hidden])) .album-layout__main { padding-bottom: 8rem; }
.player__artwork {
  width: 44px;
  height: 44px;
  object-fit: cover;
  border-radius: 3px;
  flex: 0 0 44px;
}
.player__artwork[hidden] { display: none; }
.player__title {
  font-family: var(--font-display);
  font-style: italic;
  color: var(--parchment);
  white-space: nowrap;
  overflow: hidden;
  max-width: 32%;
  min-width: 0;
}
.player__title-text { display: inline-block; }
/* De breedte van de vervaging aan de rand. Staat hier en niet pas op de variant,
   omdat de controller hem moet kunnen uitlezen vóórdat de animatie begint. */
.player__title { --player-title-fade: 48px; }
/* Past de titel niet, dan loopt hij rustig heen en weer en vervaagt de rand waar hij
   afloopt; stilstaand afgekapt leest als een fout. De breedte van die vervaging staat
   hier omdat de controller hem meetelt: zonder dat zou het einde van de titel precies
   ónder de vervaging tot stilstand komen. */
.player__title--scrolling {
  mask-image: linear-gradient(to right, #000 calc(100% - var(--player-title-fade)), transparent);
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - var(--player-title-fade)), transparent);
}
.player__title--scrolling .player__title-text {
  animation: player-title 10s var(--ease-fade) infinite;
}
/* Even stilstaan om te kunnen beginnen met lezen, dan rustig heen en weer. Langer
   wachten dan dit en je denkt dat er niets gebeurt. */
@keyframes player-title {
  0%, 8% { transform: translateX(0); }
  45%, 62% { transform: translateX(var(--player-title-shift, 0)); }
  100% { transform: translateX(0); }
}
/* Zonder beweging heeft een vervaagde rand geen zin: dan hoort er gewoon een
   beletselteken te staan, en daarvoor moet de tekst weer inline zijn. */
@media (prefers-reduced-motion: reduce) {
  .player__title--scrolling {
    mask-image: none;
    -webkit-mask-image: none;
    text-overflow: ellipsis;
  }
  .player__title--scrolling .player__title-text { animation: none; display: inline; }
}
.player__bar { display: flex; align-items: center; gap: 1rem; }
/* De ingebouwde bediening van de browser volgt color-scheme. Zonder dit staat er
   een lichtgrijze balk in een verder donkere speler. */
.player__audio { flex: 1 1 auto; min-width: 0; color-scheme: dark; }
.player__audio::-webkit-media-controls-panel { background-color: var(--earth-deep); }
.player[hidden] { display: none; }

/* ===== Admin ===== */
.admin-track-row .form-control-sm { max-width: 5rem; }
.upload-hint { font-size: 0.75rem; color: var(--fog-grey); }

/* What is attached right now, above the file field. */
.current-file {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 0.5rem;
  padding: 0.5rem 0.75rem;
  background: rgba(var(--creme-rgb), 0.04);
  border: 1px solid rgba(var(--creme-rgb), 0.12);
  border-radius: 4px;
}
.current-file__thumb {
  width: 40px;
  height: 40px;
  object-fit: cover;
  border-radius: 3px;
  flex: 0 0 40px;
}
.current-file__body { min-width: 0; }
.current-file__name {
  display: block;
  color: var(--parchment);
  font-size: 0.875rem;
  text-decoration: underline;
  text-decoration-color: rgba(var(--creme-rgb), 0.3);
  text-underline-offset: 3px;
  overflow-wrap: anywhere;
}
.current-file__name:hover { color: var(--gold-muted); text-decoration-color: var(--gold-muted); }
.current-file__meta { font-size: 0.75rem; color: var(--fog-grey); }

/* Bootstrap's checkbox blue has no business in this palette. */
.form-check-input { border-color: var(--border-field); }
.form-check-input:checked {
  background-color: var(--gold-muted);
  border-color: var(--gold-muted);
}
.form-check-input:focus {
  border-color: var(--gold-muted);
  box-shadow: 0 0 0 0.2rem rgba(var(--goud-rgb), 0.15);
}

/* ===== Square crop picker ===== */
.crop { margin-bottom: 0.75rem; }
.crop__stage {
  position: relative;
  display: inline-block;
  max-width: 100%;
  line-height: 0;
  background: var(--earth-deep);
  border: 1px solid rgba(var(--creme-rgb), 0.12);
  border-radius: 4px;
  overflow: hidden;
}
.crop__image {
  display: block;
  max-width: 100%;
  max-height: 380px;
  width: auto;
  user-select: none;
  -webkit-user-drag: none;
}
.crop__box {
  position: absolute;
  border: 2px solid var(--gold-muted);
  box-shadow: 0 0 0 9999px rgba(var(--grond-diep-rgb), 0.6);
  cursor: move;
  touch-action: none;
}
.crop__handle {
  position: absolute;
  right: -7px;
  bottom: -7px;
  width: 14px;
  height: 14px;
  background: var(--gold-muted);
  border-radius: 2px;
  cursor: nwse-resize;
  touch-action: none;
}
.crop__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-top: 0.4rem;
}

/* ===== Track page ===== */
.track-credits {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.35rem 1.25rem;
  font-size: 0.9rem;
  margin: 0;
}
.track-credits dt { color: var(--fog-grey); font-weight: 400; }
.track-credits dd { color: var(--parchment-dim); margin: 0; }

/* Drents and the translation side by side, stacked on a phone. */
.lyrics {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 2rem 3rem;
}
.lyrics__text {
  font-family: var(--font-body);
  font-size: 1.15rem;
  line-height: 1.75;
  color: var(--parchment);
}
.lyrics__text p { margin-bottom: 1.4em; }
/* Niet cursief: het is een hele kolom lopende tekst, en daar is een cursief niet
   voor gemaakt. Dat de vertaling van het Drentse origineel te onderscheiden is,
   doet de kleur al. */
.lyrics__column--translation .lyrics__text {
  color: var(--fog-light);
}

/* ===== Stories ===== */
.story { max-width: 46rem; }
.story__cover {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  border-radius: 3px;
  display: block;
  margin: 0 0 1.75rem;
}
/* Niet cursief. Dat leest lastig over vier regels achter elkaar: een cursief
   is gemaakt om één woord uit rechte tekst te lichten, niet om zelf een alinea
   te dragen. Het onderscheid met de lopende tekst zit al in de grootte en de
   kleur — lichter en groter dan de rest — en dat is genoeg. Vet zou het ook
   oplossen, maar dan gaat de samenvatting concurreren met de kop erboven. */
.story__summary {
  font-family: var(--font-body);
  font-size: 1.3rem;
  line-height: 1.45;
  color: var(--parchment);
  margin-bottom: 2rem;
}
.story__body {
  font-family: var(--font-body);
  /* EB Garamond wil een tikje meer grootte en juist wat minder interlinie dan een
     schreefloze. Action Text zet zijn eigen line-height op de .trix-content waar
     het de tekst in wikkelt, dus die hier alleen zetten verandert niets — dat
     binnenste element moet ook genoemd worden. */
  font-size: 1.2rem;
  color: var(--parchment-dim);
}
.story__body,
.story__body .trix-content { line-height: 1.4; }

/* Trix writes paragraphs as divs and separates them with an empty line, so the
   space between them is a blank line rather than a margin. No extra margin here:
   that would land on top of a gap that is already there. */
.story__body h1, .story__body h2, .story__body h3 {
  font-family: var(--font-display);
  color: var(--parchment);
  margin: 2rem 0 0.75rem;
}
.story__body a { color: var(--gold-muted); }
.story__body blockquote {
  border-left: 2px solid var(--gold-low);
  padding-left: 1.25rem;
  margin: 1.5rem 0;
  font-style: italic;
  color: var(--parchment);
}
.story__body img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 3px;
  margin: 1.5rem 0;
}
.story__thumb {
  width: 80px;
  height: 80px;
  object-fit: cover;
  border-radius: 3px;
  flex: 0 0 80px;
}

/* Trix in the admin, on a dark ground. */
trix-editor {
  background: rgba(var(--creme-rgb), 0.04);
  border-color: rgba(var(--creme-rgb), 0.18);
  color: var(--parchment);
  min-height: 16rem;
}
trix-toolbar .trix-button {
  background: var(--earth-mid);
  color: var(--parchment);
  border-color: rgba(var(--creme-rgb), 0.12);
}
/* Trix draws its toolbar icons as dark images, which disappear on this ground. */
trix-toolbar .trix-button--icon::before { filter: invert(1); opacity: 0.75; }
trix-toolbar .trix-button--icon:hover::before,
trix-toolbar .trix-button--icon.trix-active::before { opacity: 1; }
trix-toolbar .trix-button.trix-active { background: var(--gold-low); }
trix-toolbar .trix-dialog {
  background: var(--earth-warm);
  border-color: rgba(var(--creme-rgb), 0.12);
}
trix-toolbar .trix-input--dialog {
  background: rgba(var(--creme-rgb), 0.06);
  border-color: var(--border-field);
  color: var(--parchment);
}

/* Photo with a remove tick, in the story form. */
.photo-tile {
  display: block;
  width: 96px;
  cursor: pointer;
}
.photo-tile__image {
  width: 96px;
  height: 96px;
  object-fit: cover;
  border-radius: 3px;
  display: block;
}
.photo-tile__remove {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.7rem;
  color: var(--fog-grey);
  margin-top: 0.35rem;
}
.photo-tile:has(:checked) .photo-tile__image { opacity: 0.35; }
.photo-tile:has(:checked) .photo-tile__remove { color: var(--gold-muted); }

/* Just uploaded, not saved yet — marked so it reads as different from the rest. */
.photo-tile--new { cursor: default; }
.photo-tile--new .photo-tile__image { outline: 2px solid var(--gold-muted); outline-offset: -2px; }

/* What an image field reports while its file is on its way to the bucket. */
.upload-status:not([hidden]) { margin-top: 0.4rem; }
.upload-status__line {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  font-size: 0.75rem;
  color: var(--fog-grey);
  padding: 0.15rem 0;
}
.upload-status__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.upload-status__state { flex: none; font-variant-numeric: tabular-nums; }
.upload-status__line--done .upload-status__state { color: var(--gold-muted); }
.upload-status__line--failed .upload-status__state { color: #c86d5e; }

/* The code from the sticker: typed rarely, but when it is, in a dark room. */
.app-code-field {
  font-family: var(--font-meta);
  font-size: 1.75rem;
  letter-spacing: 0.4em;
  text-transform: uppercase;
  padding-left: 0.4em;
}

/* ===== Embedded video: a still until someone presses play ===== */
.video-embed {
  position: relative;
  display: block;
  margin: 1.5rem 0;
  aspect-ratio: 16 / 9;
  background: var(--earth-deep);
  border-radius: 3px;
  overflow: hidden;
  border: 0;
}
.video-embed__thumb {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  margin: 0;
}
.video-embed__play {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 3rem;
  color: var(--parchment);
  text-shadow: 0 2px 20px rgba(var(--grond-diep-rgb), 0.8);
  background: rgba(var(--grond-diep-rgb), 0.25);
  transition: background var(--dur-fast) var(--ease-fade);
}
.video-embed:hover .video-embed__play { background: rgba(var(--grond-diep-rgb), 0.1); }
.video-embed__frame { width: 100%; height: 100%; border: 0; display: block; }
.video-embed--editor { cursor: default; }

/* ===== Photo carousel ===== */
.carousel {
  position: relative;
  margin-top: 2rem;
}
.carousel__track {
  display: flex;
  gap: 1rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-left: 0;
  /* The scrollbar is the arrows' job here. */
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.carousel__track::-webkit-scrollbar { display: none; }
/* The fraction is what leaves a sliver of the next one showing, so it reads as a
   row that continues. min-width: 0 because a flex item otherwise never goes below
   its own content width — a 900px photo would simply ignore the basis. */
.carousel__photo,
.carousel__item {
  flex: 0 0 calc((100% - 1rem) / 2.3);
  min-width: 0;
  scroll-snap-align: start;
  margin: 0;
}
.carousel__photo {
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: 3px;
}
/* Cards carry more than a photo, so they need more room than one. How many fit
   follows the width of the carousel itself, not the window: on the dashboard it
   stands in a column beside the album, everywhere else across the full page. */
.carousel--cards { container-type: inline-size; }
.carousel--cards .carousel__item { flex-basis: calc((100% - 1rem) / 1.25); }
@container (min-width: 700px) {
  .carousel--cards .carousel__item { flex-basis: calc((100% - 2rem) / 2.3); }
}
@container (min-width: 1100px) {
  .carousel--cards .carousel__item { flex-basis: calc((100% - 2rem) / 3.3); }
}
@media (min-width: 768px) {
  .carousel__photo { flex-basis: calc((100% - 2rem) / 3.3); }
}

/* De kop, met rechts de uitweg naar alles als dit maar een greep is. */
.stories-list__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
}
.stories-list__all {
  flex: none;
  font-size: 0.8rem;
  color: var(--fog-grey);
  text-decoration: none;
  white-space: nowrap;
}
.stories-list__all:hover { color: var(--gold-muted); }

/* Against the heading, so it lines up with whatever stands next to it. */
.stories-list--tight .carousel { margin-top: 0; }

/* Album en verhalen naast elkaar, vanaf het punt waar dat past. De albumkaart en
   een verhaalkaart krijgen dezelfde breedte in plaats van elk een deel van een
   raster: naast elkaar hoort het één rij kaarten te lijken. De verhalen vullen de
   rest, dus hoeveel er passen volgt vanzelf uit de breedte van het scherm. */
.dashboard-panels { --dashboard-card: 22rem; }
@media (min-width: 1200px) {
  .dashboard-panels--side-by-side {
    display: flex;
    align-items: flex-start;
    gap: 1.5rem;
  }
  .dashboard-panels--side-by-side .dashboard-panels__album {
    flex: 0 0 var(--dashboard-card);
  }
  .dashboard-panels--side-by-side .dashboard-panels__stories {
    flex: 1 1 auto;
    min-width: 0;
  }
  .dashboard-panels--side-by-side .carousel--cards .carousel__item {
    flex-basis: var(--dashboard-card);
  }
}
.carousel__arrow {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 3.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  font-size: 3rem;
  line-height: 1;
  color: var(--parchment);
  text-shadow: 0 2px 12px rgba(var(--grond-diep-rgb), 0.9);
  background: linear-gradient(to right, rgba(var(--grond-diep-rgb), 0.45), transparent);
  opacity: 0.85;
  transition: opacity var(--dur-fast) var(--ease-fade);
}
.carousel__arrow:hover { opacity: 1; }
.carousel__arrow[hidden] { display: none; }
.carousel__arrow--previous { left: 0; }
.carousel__arrow--next {
  right: 0;
  background: linear-gradient(to left, rgba(var(--grond-diep-rgb), 0.45), transparent);
}

/* ===== Story cards ===== */
.story-card { overflow: hidden; }
.story-card__image {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  display: block;
  margin: 0;
}
.story-card__image--empty { background: var(--earth-mid); }
.story-card__title {
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: 400;
  line-height: 1.25;
  color: var(--parchment);
  margin: 0 0 0.35rem;
}
.story-card:hover .story-card__title { color: var(--gold-muted); }
.story-card__date {
  font-size: 0.8rem;
  color: var(--fog-grey);
  margin: 0 0 0.5rem;
}
.story-card__topics {
  display: flex;
  gap: 0.3rem;
  padding: 0 1rem 0.9rem;
  margin-top: auto;
  overflow-x: auto;
  justify-content: flex-end;
  scrollbar-width: none;
}
.story-card__topics::-webkit-scrollbar { display: none; }
.story-card__topics .topic { flex: 0 0 auto; }
.topic--small { font-size: 0.72rem; padding: 0.1rem 0.45rem; }

/* Three lines and then an ellipsis, so a long summary cannot make one card taller
   than the rest of the row. */
.story-card__summary {
  font-size: 0.9rem;
  line-height: 1.5;
  color: var(--parchment-dim);
  margin: 0;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ===== Form actions, pinned to the bottom ===== */
.form-bar {
  position: sticky;
  bottom: 0;
  z-index: 1020;
  margin-top: 1.5rem;
  padding: 0.75rem 0;
  background: rgba(var(--grond-diep-rgb), 0.94);
  backdrop-filter: blur(14px) saturate(115%);
  -webkit-backdrop-filter: blur(14px) saturate(115%);
  border-top: 1px solid rgba(var(--creme-rgb), 0.1);
}
/* button_to wraps its button in a form; that form should not take up a row. */
.form-bar form { display: inline; }

/* A description that stays level with the artwork next to it, until you open it. */
.track-description {
  display: -webkit-box;
  -webkit-line-clamp: 8;
  line-clamp: 8;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.track-description.is-open {
  display: block;
  -webkit-line-clamp: none;
  line-clamp: none;
}
/* De zijkolom is smaller dan de nummerpagina; acht regels is daar te veel. */
.track-description--panel { -webkit-line-clamp: 4; line-clamp: 4; }
.track-description p:last-child { margin-bottom: 0; }
.track-description__more {
  color: var(--gold-muted);
  text-decoration: none;
}
.track-description__more:hover { color: var(--parchment); }

/* Step buttons in the player. */
.player__steps { display: flex; gap: 0.25rem; flex: 0 0 auto; }
.player__step {
  width: 2rem;
  height: 2rem;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--parchment);
  font-size: 1.5rem;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: color var(--dur-fast) var(--ease-fade), background var(--dur-fast) var(--ease-fade);
}
.player__step:hover:not(:disabled) { color: var(--gold-muted); background: rgba(var(--creme-rgb), 0.08); }
.player__step:disabled { opacity: 0.25; cursor: default; }

/* De twee knoppen die een laag openen, met een aan-staat zoals in een muziekspeler.
   Ze staan achter de speler in plaats van ervoor: de bediening van de muziek hoort
   het dichtst bij de muziek. */
.player__buttons { display: flex; align-items: center; gap: 0.4rem; flex: 0 0 auto; order: 1; }
.player__toggle, .player__more {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  flex: 0 0 auto;
  border: 1px solid rgba(var(--creme-rgb), 0.18);
  border-radius: 999px;
  background: none;
  color: var(--parchment-dim);
  font-family: var(--font-meta);
  font-size: 0.75rem;
  letter-spacing: 0.06em;
  padding: 0.3rem 0.8rem;
  transition: color var(--dur-fast) var(--ease-fade), border-color var(--dur-fast) var(--ease-fade);
}
.player__icon { display: inline-flex; line-height: 0; }
.player__more .player__icon { transition: rotate var(--dur-fast) var(--ease-fade); }
.player__more.is-active .player__icon { rotate: 180deg; }
.player__toggle:hover:not(:disabled), .player__more:hover { color: var(--gold-muted); border-color: var(--gold-muted); }
/* Staat de laag open, dan staat de knop aan — en brengt hij je er ook weer uit. */
.player__toggle.is-active, .player__more.is-active {
  color: var(--gold-muted);
  border-color: var(--gold-muted);
  background: rgba(var(--goud-rgb), 0.15);
}
.player__toggle:disabled { opacity: 0.3; }
/* "meer info" bestaat alleen waar de zijkolom niet naast de lijst past. */
.player__more { display: none; }
@media (max-width: 1199.98px) { .player__more { display: inline-flex; } }

/* Op een telefoon past het niet op één regel. Dan de hoes twee regels hoog, met de
   titel erboven en de knoppen eronder — zelfde opbouw als de kop van het album — en
   de bediening op een regel daaronder. */
@media (max-width: 575.98px) {
  .player__bar {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-areas:
      "artwork title"
      "artwork buttons"
      "steps   audio";
    align-items: center;
    gap: 0.4rem 0.75rem;
  }
  .player__artwork { grid-area: artwork; width: 66px; height: 66px; flex: none; }
  .player__title { grid-area: title; max-width: none; font-size: 0.9rem; align-self: end; }
  .player__buttons { grid-area: buttons; align-self: start; }
  .player__steps { grid-area: steps; }
  .player__audio { grid-area: audio; }
  body:has(.player:not([hidden])) main { padding-bottom: 12rem !important; }
  body:has(.player:not([hidden])) .album-layout__main { padding-bottom: 12rem; }
}

/* ===== Bevestigen voor iets buiten de browser om =====
   Een native <dialog>: showModal() regelt focus, achtergrond en Escape zelf. */
.confirm {
  width: min(26rem, calc(100vw - 2rem));
  padding: 1.25rem;
  border: 1px solid rgba(var(--creme-rgb), 0.16);
  border-radius: 8px;
  background: var(--earth-deep);
  color: var(--parchment);
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.5);
}
.confirm::backdrop {
  background: rgba(var(--grond-diep-rgb), 0.72);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}
.confirm__actions { display: flex; justify-content: flex-end; flex-wrap: wrap; gap: 0.5rem; }

/* ===== Photo, full size ===== */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 1080;
  background: rgba(var(--grond-diep-rgb), 0.94);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 3rem 1.5rem;
  cursor: zoom-out;
}
.lightbox__image {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  cursor: default;
  border-radius: 3px;
}
.lightbox__close {
  position: absolute;
  top: 1rem;
  right: 1.25rem;
  border: 0;
  background: none;
  color: var(--parchment);
  font-size: 2.5rem;
  line-height: 1;
}
.lightbox__close:hover { color: var(--gold-muted); }
/* A photo you can open says so. */
.carousel__photo, .story__cover, .track-page-artwork { cursor: zoom-in; }

/* ===== Tag field ===== */
.tag-field {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem;
  padding: 0.35rem 0.5rem;
  background: rgba(var(--creme-rgb), 0.04);
  border: 1px solid var(--border-field);
  border-radius: 4px;
}
.tag-field:focus-within { border-color: var(--gold-muted); }
.tag-field__chips { display: contents; }
.tag-field__input {
  flex: 1 1 6rem;
  min-width: 6rem;
  border: 0;
  background: none;
  color: var(--parchment);
  outline: none;
  padding: 0.25rem 0;
}
.tag-field__input::placeholder { color: rgba(var(--creme-rgb), 0.35); }
.tag-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.15rem 0.3rem 0.15rem 0.55rem;
  background: rgba(var(--goud-rgb), 0.15);
  border: 1px solid rgba(var(--goud-rgb), 0.35);
  border-radius: 3px;
  font-size: 0.85rem;
  color: var(--parchment);
}
.tag-chip__remove {
  border: 0;
  background: none;
  color: var(--fog-grey);
  line-height: 1;
  font-size: 1rem;
  padding: 0 0.15rem;
}
.tag-chip__remove:hover { color: var(--gold-muted); }

/* ===== What a story is about, and what to read next ===== */
.topic-cloud { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.topic {
  display: inline-block;
  padding: 0.2rem 0.6rem;
  border: 1px solid rgba(var(--goud-rgb), 0.35);
  border-radius: 3px;
  font-size: 0.85rem;
  color: var(--gold-muted);
  text-decoration: none;
  background: rgba(var(--goud-rgb), 0.08);
}
a.topic:hover { color: var(--parchment); border-color: var(--gold-muted); background: rgba(var(--goud-rgb), 0.2); }
.topic--plain { color: var(--fog-light); border-color: rgba(var(--creme-rgb), 0.18); background: none; }
.related__thumb {
  width: 48px;
  height: 48px;
  object-fit: cover;
  border-radius: 3px;
  flex: 0 0 48px;
}
