/* Sora variable font, self-hosted. wght axis gives all weights from Light to ExtraBold. */
@font-face {
  font-family: "Sora";
  font-style: normal;
  font-weight: 100 800;
  font-display: swap;
  src: url("/assets/fonts/sora-variable-latin.woff2") format("woff2");
}

/*
  Theme: palette of the current release (Saudade Do Sol): sun and sky.
  The page background is a soft mesh gradient built from the mesh colors below, text is always near black.
  For a release with a different cover, add a body class (e.g. .theme-new-slug) below and override these variables.
*/
:root {
  --color-paper: #fff6dc;
  --color-mesh-sky: #a9bfd3;      /* cool slate, the complement of the walnut, sits behind the turntable */
  --color-mesh-sun: #f6e3a6;      /* butter, from the yellow of the record */
  --color-mesh-lilac: #e8c9b4;    /* dusty rose, between wood and silver */
  --color-mesh-apricot: #f0c47e;  /* honey */
  --color-mesh-coral: #d98a56;    /* clay, from the walnut */
  --sky-pos: 50% 16%;
  --sky-size: 70% 42%;
  --color-text: #0f0b05;
  --color-muted: #2e2610;

  --font-heading: "Sora", system-ui, sans-serif;
  --font-body: "Sora", system-ui, sans-serif;

  --space-1: 4px;
  --space-2: 8px;
  --space-3: 16px;
  --space-4: 24px;
  --space-5: 40px;
  --space-6: 64px;

  --radius: 0;
  --line: 1px solid currentColor; /* currentColor, so lines follow the text color of dark pages */
  --line-strong: 2px solid currentColor;

  --fs-label: 0.75rem;
  --fs-small: 0.875rem;
  --fs-body: 1rem;
  --fs-h2: 2rem;
  --fs-h1: clamp(2.75rem, 11vw, 6.5rem);

  --nav-h: calc(64px + env(safe-area-inset-top, 0px));   /* the page is drawn under the status bar on phones (viewport-fit=cover), the menu bar starts below it */
  /* side gutter, grows on wide screens so content stays 1100px wide */
  --gutter: max(var(--space-3), calc((100vw - 1100px) / 2));
}

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

html { scroll-padding-top: var(--nav-h); }
/* The colour behind the page on Home (the wood is a layer on top of it). The dark pages and About have no colour here on purpose: their gradient on the body
   then paints the whole window, also where it is taller than the page, so there is no second colour at the bottom of a short page. */
html:has(body.theme-table) { background-color: #3a2414; }
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

html, body { overscroll-behavior: none; }   /* no rubber-band pulling of the page on phones, like About */

body {
  --bottom-fade: linear-gradient(transparent, transparent);   /* the dark pages fade their gradient into the dark base colour at the bottom edge, see body.theme-dark */
  --mesh:
    var(--bottom-fade),
    radial-gradient(var(--sky-size) at var(--sky-pos), var(--color-mesh-sky) 0%, transparent 100%),
    radial-gradient(60% 55% at 4% 4%, var(--color-mesh-sun) 0%, transparent 100%),
    radial-gradient(55% 50% at 52% 52%, var(--color-mesh-lilac) 0%, transparent 100%),
    radial-gradient(60% 55% at 6% 96%, var(--color-mesh-apricot) 0%, transparent 100%),
    radial-gradient(65% 60% at 98% 98%, var(--color-mesh-coral) 0%, transparent 100%),
    var(--color-paper);
  --menu-tint: var(--color-paper);   /* colour laid over the blurred page behind the menu, follows the page theme */
  margin: 0;
  min-height: 100vh;
  min-height: 100svh;   /* not taller than the visible screen on phones, otherwise short pages scroll for nothing */
  background: var(--mesh);
  background-repeat: no-repeat;
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 1.5;
  overflow-x: hidden;
}

/* Page themes. Home and release pages use the cover colors (see :root). Other pages are dark, because not every
   release will have the colors of the current cover. The about page takes its colors from the portrait photo. */
body.theme-dark {
  --bottom-fade: linear-gradient(to top, var(--color-paper) 0, transparent 170px);   /* the edge of the page is the plain dark colour (no brown corner), so the bar of the phone under it has one colour */
  --color-paper: #0f0e0c;
  --color-mesh-sky: #1c222d;
  --color-mesh-sun: #2a2316;
  --color-mesh-lilac: #1a1620;
  --color-mesh-apricot: #28201a;
  --color-mesh-coral: #33231a;
  --color-text: #f3ede2;
  --color-muted: #b9b0a0;
}
body.theme-about {
  --color-paper: #14100c;
  --color-mesh-sky: #2b3340;
  --color-mesh-sun: #2c2a1e;
  --color-mesh-lilac: #1c1713;
  --color-mesh-apricot: #3a2a1d;
  --color-mesh-coral: #4c3122;
  --color-text: #f3ebdd;
  --color-muted: #bfb29b;
}

/* Home: a wooden table top fills the screen (one photo, scaled to cover). Light text, because the wood is a mid dark brown. */
body.theme-table {
  --color-text: #fff6dc;
  --color-muted: #e6d6b4;
  --mesh: linear-gradient(rgba(15, 8, 2, 0.22), rgba(15, 8, 2, 0.22)), url("/assets/images/wood.jpg");
  background: transparent;     /* the wood is the layer below (::before), the colour behind it is set on html */
  --menu-tint: #1c1008;
}
/* The wood is its own fixed layer behind the page (not background-attachment: fixed, which phones do not support). One large photo of a table top,
   2496 x 1664, scaled to cover the whole screen, also under the bars of the phone. */
body.theme-table::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  background: var(--mesh) center / cover no-repeat;
}
/* things on the table */
.deck__plant, .deck__lamp, .deck__polaroid, .deck__cup, .deck__marker { display: none; }
@media (min-width: 768px) {
  /* things on the table, from tablet width up. Sizes and positions are percentages of the deck width. */
  /* espresso cup: at the lower left of the record sleeve, just a little over it. The light comes from the upper right, so the shadow falls down and to the left. */
  /* Green marker (BUMIMA) lying at the lower right corner of the polaroid and touching it a little. A 14 cm marker next to a 8.8 cm wide polaroid:
     its length is about 1.6 times the width of the polaroid, so its picture (a diagonal, about 0.7 times the length wide) is 24 percent of the deck. */
  .deck__marker {
    display: block;
    position: absolute;
    z-index: -1;
    width: 24%;
    left: 133%;
    top: 66%;
    height: auto;
    transform: rotate(-58deg);   /* the picture shows the marker running down to the right, this turns it to lie almost flat, rising a little to the right */
    filter:
      drop-shadow(calc(var(--deck-w) * -0.0020) calc(var(--deck-w) * 0.0045) calc(var(--deck-w) * 0.0020) rgba(25, 14, 4, 0.55))
      drop-shadow(calc(var(--deck-w) * -0.0075) calc(var(--deck-w) * 0.0160) calc(var(--deck-w) * 0.0080) rgba(25, 14, 4, 0.34))
      drop-shadow(calc(var(--deck-w) * -0.0150) calc(var(--deck-w) * 0.0330) calc(var(--deck-w) * 0.0200) rgba(25, 14, 4, 0.18));
    pointer-events: none;
  }
  .deck__cup {
    display: block;
    position: absolute;
    z-index: -1;
    width: 30%;      /* the saucer is about 40 percent of the sleeve (12 to 14 cm against 31.5 cm), the picture includes the spoon and the handle */
    left: -65%;
    top: 75.5%;
    height: auto;
    transform: rotate(-24deg);
    filter:
      drop-shadow(calc(var(--deck-w) * -0.0020) calc(var(--deck-w) * 0.0045) calc(var(--deck-w) * 0.0020) rgba(25, 14, 4, 0.55))
      drop-shadow(calc(var(--deck-w) * -0.0075) calc(var(--deck-w) * 0.0160) calc(var(--deck-w) * 0.0080) rgba(25, 14, 4, 0.36))
      drop-shadow(calc(var(--deck-w) * -0.0150) calc(var(--deck-w) * 0.0330) calc(var(--deck-w) * 0.0200) rgba(25, 14, 4, 0.20));
  }
  .deck__plant {
    display: block;
    position: absolute;
    z-index: -1;               /* above the sleeve (later in the markup), below the deck */
    width: 33%;
    left: -37%;
    top: 4%;
    height: auto;
    transform: rotate(-12deg);
    /* Realistic shadow: three layers like a real one. A tight dark contact shadow where the pot and the lowest leaves touch the paper,
       a medium one, and a wide, faint, blurred one for the leaves that are higher up. The further away from the paper, the more the
       shadow moves out and the softer it gets. The light comes from above and a little from the right (the lamp), so the shadow falls
       down and a little to the left. The element is rotated by -12deg, so the offsets are given in its own frame (-0.45 / 0.93). */
    filter:
      drop-shadow(calc(var(--deck-w) * -0.0030) calc(var(--deck-w) * 0.0070) calc(var(--deck-w) * 0.0022) rgba(25, 14, 4, 0.55))
      drop-shadow(calc(var(--deck-w) * -0.0080) calc(var(--deck-w) * 0.0190) calc(var(--deck-w) * 0.0080) rgba(25, 14, 4, 0.36))
      drop-shadow(calc(var(--deck-w) * -0.0160) calc(var(--deck-w) * 0.0390) calc(var(--deck-w) * 0.0200) rgba(25, 14, 4, 0.20));
  }
  .deck__lamp {
    display: block;
    position: absolute;
    z-index: -1;
    width: 48%;
    left: 103%;
    top: 14%;
  }
  /* polaroid below the lamp, tilted to the lower left: the opposite of the record sleeve */
  .deck__polaroid {
    display: block;
    position: absolute;
    z-index: -1;
    width: 21%;
    left: 116%;
    top: 76%;
    height: auto;
    transform: rotate(9deg);
    filter: drop-shadow(0 8px 10px rgba(10, 5, 0, 0.45));
  }
  .deck__lamp img {
    position: relative;
    display: block;
    width: 100%;
    height: auto;
    filter: saturate(1.35) brightness(1.1) drop-shadow(0 14px 16px rgba(10, 5, 0, 0.45)) drop-shadow(0 0 14px rgba(255, 140, 30, 0.7));
    animation: lamp-flicker 5.3s linear infinite;
  }
  /* the warm light the lamp throws onto the table */
  .deck__lamp::before {
    content: "";
    position: absolute;
    inset: -55%;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(255, 150, 40, 0.6) 0, rgba(255, 120, 20, 0.28) 32%, rgba(255, 100, 10, 0) 68%);
    mix-blend-mode: screen;
    pointer-events: none;
    animation: lamp-glow 5.3s linear infinite;
  }
}
@keyframes lamp-glow {
  0%, 100% { opacity: 1; } 7% { opacity: 0.86; } 10% { opacity: 1; } 28% { opacity: 0.93; } 31% { opacity: 1; }
  52% { opacity: 0.82; } 55% { opacity: 0.97; } 58% { opacity: 0.9; } 79% { opacity: 0.95; } 83% { opacity: 1; }
}
@keyframes lamp-flicker {
  0%, 100% { filter: saturate(1.35) brightness(1.1) drop-shadow(0 14px 16px rgba(10, 5, 0, 0.45)) drop-shadow(0 0 14px rgba(255, 140, 30, 0.7)); }
  7% { filter: saturate(1.3) brightness(1.02) drop-shadow(0 14px 16px rgba(10, 5, 0, 0.45)) drop-shadow(0 0 9px rgba(255, 140, 30, 0.5)); }
  10% { filter: saturate(1.35) brightness(1.1) drop-shadow(0 14px 16px rgba(10, 5, 0, 0.45)) drop-shadow(0 0 14px rgba(255, 140, 30, 0.7)); }
  52% { filter: saturate(1.3) brightness(1) drop-shadow(0 14px 16px rgba(10, 5, 0, 0.45)) drop-shadow(0 0 8px rgba(255, 140, 30, 0.45)); }
  55% { filter: saturate(1.35) brightness(1.08) drop-shadow(0 14px 16px rgba(10, 5, 0, 0.45)) drop-shadow(0 0 13px rgba(255, 140, 30, 0.65)); }
}
@media (prefers-reduced-motion: reduce) {
  .deck__lamp img, .deck__lamp::before { animation: none; }
}
/* the deck stands on the table */
body.theme-table .deck__base { box-shadow: 0 24px 40px rgba(10, 5, 0, 0.5), 0 4px 10px rgba(10, 5, 0, 0.4); }

/* Film grain over everything. A picture of fine specks, half white and half black with the same strength, drawn with normal transparency:
   on average it neither lightens nor darkens. (Before it was an SVG noise with mix-blend-mode overlay: in Safari the blend mode stopped working a moment
   after the page had loaded and the grey noise then lightened the whole page, the wood got too bright.) One value per device pixel, a 240px tile for
   normal and a 480px tile for retina screens, both drawn at 240 CSS px. */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 100;
  pointer-events: none;
  background-image: url("/assets/images/film-1x.webp");
  background-image: image-set(url("/assets/images/film-1x.webp") 1x, url("/assets/images/film-2x.webp") 2x);
  background-size: 240px 240px;
}

/* The home page and About are made of photos that have their own texture (the portrait has its grain in the photo): no grain layer over them */
body.theme-about::after {
  display: none;
}
/* Home: no grain over the photos, instead (phones only) the wood fades into a darker brown at the top and the bottom edge, so the bars of the browser
   do not look like separate blocks. */
body.theme-table::after { background: none; opacity: 1; mix-blend-mode: normal; z-index: 2; }
/* Home on phones: the edge colour is exactly the colour of the browser bars (theme-color, see the html rule above), solid where the bars are and fading
   into the wood over about 100px, so the bars and the page flow into each other. */
@media (max-width: 767px) {
  body.theme-table::after {
    background: linear-gradient(to bottom,
      #3a2414 0,
      #3a2414 env(safe-area-inset-top, 0px),
      transparent calc(env(safe-area-inset-top, 0px) + 80px),
      transparent calc(100% - env(safe-area-inset-bottom, 0px) - 130px),
      #3a2414 calc(100% - env(safe-area-inset-bottom, 0px)),
      #3a2414 100%);
  }
  /* The dark pages and About have no fade at the edges: their gradient (and the photo) simply goes on under the status bar and the toolbar of the phone, so there is no band. */
}

/* The open menu still gets the grain on these two pages (on the dark pages the page grain lies over it already) */
body.theme-table .nav__menu::after,
body.theme-about .nav__menu::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: url("/assets/images/film-1x.webp");
  background-image: image-set(url("/assets/images/film-1x.webp") 1x, url("/assets/images/film-2x.webp") 2x);
  background-size: 240px 240px;
}

h1, h2 {
  font-family: var(--font-heading);
  font-weight: 600;
  line-height: 0.9;
  letter-spacing: -0.05em;
  margin: 0 0 var(--space-4);
}
h2 { font-size: var(--fs-h2); }

a { color: var(--color-text); text-underline-offset: 4px; text-decoration-thickness: 1px; }
img { max-width: 100%; height: auto; display: block; }
:focus-visible { outline: 2px solid var(--color-text); outline-offset: 3px; }


/* Nav: logo left, plus icon right on every screen size. The menu is the same on every page, see below. */
.nav {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 10;
  min-height: var(--nav-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: env(safe-area-inset-top, 0px) var(--gutter) 0;
}
.nav__logo,
.nav__toggle {
  position: relative;
  z-index: 6; /* stays above the fullscreen menu */
}
.nav__logo {
  font-size: var(--fs-body);
  font-weight: 700;
  letter-spacing: 0.02em;
  text-decoration: none;
}
.nav__toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  margin-right: max(-19px, calc(var(--gutter) * -1));   /* the visible plus ends at the right edge of the content, the tap area is bigger than the plus */
  padding: 0;
  color: var(--color-text);
  background: none;
  border: 0;
  cursor: pointer;
}
.nav__icon { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: square; }   /* about as high as the text of the logo, a little thicker */
.nav__icon--close { display: none; }
.nav__toggle[aria-expanded="true"] .nav__icon--open { display: none; }
.nav__toggle[aria-expanded="true"] .nav__icon--close { display: block; }

/* Mini player in the middle of the header: appears when a track is playing (or paused halfway) while another page is open */
.nav__now {
  position: absolute;
  top: calc(50% + env(safe-area-inset-top, 0px) / 2);
  left: 50%;
  z-index: 6;                                 /* above the fullscreen menu, so it can be used there as well */
  display: flex;
  align-items: center;
  gap: 8px;
  max-width: calc(100% - 2 * (var(--gutter) + 72px));
  padding: 0 2px 0 16px;
  color: var(--color-text);
  border: 1.5px solid currentColor;     /* the same white line as the back buttons */
  transform: translate(-50%, -50%);
  /* a small piece of glass like the menu: the page behind it is blurred and tinted, with the film grain on top */
  border-radius: 999px;
  background-color: color-mix(in srgb, var(--menu-tint) 38%, transparent);
  background-image: url("/assets/images/film-1x.webp");
  background-image: image-set(url("/assets/images/film-1x.webp") 1x, url("/assets/images/film-2x.webp") 2x);
  background-size: 240px 240px;
  -webkit-backdrop-filter: blur(28px) saturate(1.1);
  backdrop-filter: blur(28px) saturate(1.1);
}
.nav__now[hidden] { display: none; }
@media (max-width: 767px) {
  /* on phones the pill sits in the free space between the logo and the plus, not in the exact middle of the screen */
  .nav__now { left: calc(50% + 20px); max-width: calc(100% - 150px); }
}
.nav__now-btn {
  position: relative;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 44px;
  padding: 0;
  color: var(--color-text);
  background: none;
  border: 0;
  cursor: pointer;
}
.nav__now-icon { width: 14px; height: 14px; fill: currentColor; }
.nav__now-icon--play { margin-left: 1px; }    /* the triangle looks centred a little right of its box */
.nav__now-icon--pause { display: none; }
.nav__now.is-playing .nav__now-icon--play { display: none; }
.nav__now.is-playing .nav__now-icon--pause { display: block; }
.nav__now-eq {
  flex: none;
  display: flex;
  align-items: flex-end;
  gap: 2px;
  width: 14px;
  height: 14px;
}
.nav__now-eq i {
  flex: 1;
  height: 100%;
  background: currentColor;
  transform: scaleY(0.3);
  transform-origin: bottom;
}
.nav__now.is-playing .nav__now-eq i { animation: eq-bar 0.9s ease-in-out infinite alternate; }
.nav__now.is-playing .nav__now-eq i:nth-child(2) { animation-duration: 0.65s; animation-delay: -0.3s; }
.nav__now.is-playing .nav__now-eq i:nth-child(3) { animation-duration: 0.8s; animation-delay: -0.55s; }
@keyframes eq-bar { from { transform: scaleY(0.25); } to { transform: scaleY(1); } }
@media (prefers-reduced-motion: reduce) {
  .nav__now.is-playing .nav__now-eq i { animation: none; transform: scaleY(0.6); }
}
.nav__now-title {
  overflow: hidden;
  font-size: var(--fs-small);
  font-weight: 600;
  line-height: 1.2;
  white-space: nowrap;
  text-overflow: ellipsis;
  text-decoration: none;
  color: var(--color-text);
}

/* All releases: link to SoundCloud, centred under the list */
.section .release-more { max-width: none; margin: var(--space-5) 0 0; font-size: var(--fs-small); font-weight: 400; text-align: center; }   /* centred under the whole list, only the word SoundCloud is the link */

/* 404 page: the picture in the middle of the page, see-through title like BUMMA on Home, outlined button */
.notfound {
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  padding: calc(var(--nav-h) + var(--space-3)) var(--gutter) var(--space-5);
  text-align: center;
}
.notfound__img { display: block; width: min(100%, 720px); height: auto; }
.notfound__title {
  margin: 0;
  font-size: clamp(2.25rem, 9vw, 4rem);   /* smaller than the page titles, so it stays under the picture */
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.05em;
  color: color-mix(in srgb, var(--color-text) 48%, transparent);
}
/* button with the same white line as the back buttons */
.btn-line {
  display: inline-flex;
  align-items: center;
  min-height: 48px;
  padding: 0 var(--space-4);
  font-size: var(--fs-small);
  color: var(--color-text);
  text-decoration: none;
  border: 1.5px solid currentColor;
  border-radius: 999px;
}

/* room for the home indicator of phones at the bottom of the scrolling pages */
.hero::after, .release::after, .section::after { content: ""; display: block; height: env(safe-area-inset-bottom, 0px); }

/* Pages that were visited stay in the document while another page is shown */
main[hidden] { display: none !important; }

/* Menu: the same on every page. It lies over the page, shows the page behind it blurred (backdrop-filter) with a light tint of the
   page colour (--menu-tint, set per theme on body), and uses the text colour of the page. Opening and closing use these timings
   on every page, the page itself decides nothing about them. */
.nav__menu {
  --in: 0.7s;            /* menu fades in */
  --out: 0.45s;          /* menu fades out */
  --item: 0.8s;          /* one item fades in and rises */
  display: flex;
  position: fixed;
  inset: 0;
  bottom: -300px;       /* reaches under the toolbar of Safari, where the page goes on beyond the fixed area, otherwise the lowest rows of a release page stay sharp */
  padding-bottom: 300px;   /* keeps the links centred on the visible screen */
  z-index: 5;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  text-align: center;
  background: color-mix(in srgb, var(--menu-tint) 38%, transparent);
  cursor: pointer;   /* a click beside the links closes the menu */
  -webkit-backdrop-filter: blur(28px) saturate(1.1);
  backdrop-filter: blur(28px) saturate(1.1);
  opacity: 0;
  visibility: hidden;   /* a closed menu cannot be clicked or reached with the keyboard */
  transition: opacity var(--out) ease, visibility 0s linear var(--out);
}
.nav__menu.is-open {
  opacity: 1;
  visibility: visible;
  transition: opacity var(--in) cubic-bezier(0.3, 0, 0.2, 1), visibility 0s;
}
.nav__menu a {
  display: block;
  cursor: pointer;
  font-size: min(clamp(2.5rem, 11vw, 5rem), 9.5vh);   /* the menu items get smaller on low windows */
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.05em;
  text-decoration: none;
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.3s ease, transform 0.3s ease;
}
.nav__menu a[aria-current="page"] { text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 0.12em; }
.nav__menu.is-open a {
  opacity: 1;
  transform: none;
  transition: opacity var(--item) ease var(--d, 0.2s), transform calc(var(--item) + 0.1s) cubic-bezier(0.2, 0.7, 0.2, 1) var(--d, 0.2s);
}
.nav__menu.is-open a:nth-child(2) { --d: 0.32s; }
.nav__menu.is-open a:nth-child(3) { --d: 0.44s; }
.nav__menu.is-open a:nth-child(4) { --d: 0.56s; }
@media (prefers-reduced-motion: reduce) {
  .nav__menu, .nav__menu.is-open, .nav__menu a, .nav__menu.is-open a { transition: none; }
}

/* no page scrolling behind the open menu */
.menu-open, .menu-open body { overflow: hidden; }
/* Safari on phones draws the page under its toolbar outside the fixed menu, so the backdrop blur never reaches the lowest rows of a release page.
   While the menu is open the link rows fade out instead, with exactly the timing of the menu (--in / --out, see .nav__menu), so they come and go
   together with the rest of the page. (A blur on the rows themselves ran on its own clock and looked out of step, a blur on the whole page showed up as a box.) */
.links { transition: opacity 0.45s ease; }
.menu-open .links { opacity: 0.12; transition: opacity 0.7s cubic-bezier(0.3, 0, 0.2, 1); }
/* Hero (home): the turntable big at the top, title, player and links below it. The page scrolls. */
.hero { position: relative; overflow: hidden; }   /* the lamp glow reaches past the screen edge */
.hero__inner {
  width: 100%;
  padding: calc(var(--nav-h) + var(--space-3)) var(--gutter) var(--space-4);
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-3);
}
.label {
  margin: 0 0 var(--space-2);
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-muted);
}
.hero__title {
  font-size: min(var(--fs-h1), 7.4vw);
  margin-bottom: var(--space-3);
  white-space: nowrap;           /* title and BUMMA stay on one line, the type scales with the screen width */
}
/* BUMMA behind the title: same type, but a see-through cream */
.hero__artist {
  margin-left: 0.28em;
  color: color-mix(in srgb, var(--color-text) 48%, transparent);
}
/* the big type has a little side bearing, pull it back so it lines up with the small text below */
.hero__title, .release__title, .page-title { margin-left: -0.04em; }

/* Turntable: photo of a deck without arm, the record on the platter, the tonearm as its own layer on top.
   All positions are percentages of the 788 x 595 deck image (measured in source/deck-geometry.json). */
.deck {
  position: relative;
  width: var(--deck-w);
  aspect-ratio: 788 / 608;
}
.deck { isolation: isolate; }
/* record sleeve: from tablet width up, lies partly under the deck on the left, tilted, as big as the record */
.deck__sleeve { display: none; }
@media (min-width: 768px) {
  .deck__sleeve {
    display: block;
    position: absolute;
    z-index: -1;
    width: 60.1%;               /* same size as the record (2 x 237 of 788) */
    left: -41%;
    top: 14%;
    height: auto;
    aspect-ratio: 1;
    transform: rotate(-7deg);
    box-shadow: 0 10px 28px rgba(15, 11, 5, 0.28), 0 2px 6px rgba(15, 11, 5, 0.2);
  }
}
.deck__base { position: absolute; inset: 0; width: 100%; height: 100%; }
.deck .disc {
  position: absolute;
  left: 11.015%;
  top: 9.289%;
  width: 60.152%;
  aspect-ratio: 1;
}
/* tonearm: rotates around its pivot. The angle is set from js/script.js (rest 0, then along the record while playing) */
.deck__arm {
  position: absolute;
  left: 73.668%;
  top: 2.773%;
  width: 19.162%;
  height: auto;
  transform-origin: 53.974% 19.450%;
  transform: rotate(var(--arm-angle, 0deg));
  pointer-events: none;
}
.deck__arm.is-swinging { transition: transform 1s cubic-bezier(0.45, 0.05, 0.25, 1); }
/* after the end of a track the arm lifts and goes home slowly */
.deck__arm.is-slow { transition: transform 2.4s cubic-bezier(0.4, 0, 0.2, 1); }
/* Speed knob: its own layer cut from the photo (the photo itself has no knob). It turns around its centre between the 33 and the 45 position. */
.deck__knob {
  position: absolute;
  left: 8.7563%;
  top: 87.6645%;
  width: 4.6954%;
  height: auto;
  transform-origin: 45.95% 40.00%;
  transform: rotate(0deg);
  transition: transform 0.45s cubic-bezier(0.3, 0.1, 0.2, 1);
  pointer-events: none;
}
.player.is-45 .deck__knob { transform: rotate(69deg); }
/* the clickable area around the knob (at least 44px, so it can be hit with a finger) */
.deck__knob-btn {
  position: absolute;
  left: 10.9137%;
  top: 90.2961%;
  width: max(44px, calc(var(--deck-w) * 0.06));
  height: max(44px, calc(var(--deck-w) * 0.06));
  transform: translate(-50%, -50%);
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
  cursor: pointer;
}
@media (prefers-reduced-motion: reduce) { .deck__knob { transition: none; } }

/* The dot of the active speed glows red while the music plays, like a small lamp: no solid dot, only a soft light on top of the photo
   that swells and fades slowly (screen blend, so it lights the metal instead of covering it). There is one light on the 33 dot and one on
   the 45 dot. Switching cross-fades them, so nothing travels across the panel. */
.deck__led {
  position: absolute;
  width: 0;
  height: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.4s ease;
}
.deck__led--33 { left: 8.566%; top: 88.569%; }
.deck__led--45 { left: 11.574%; top: 85.066%; }
.deck__led::before, .deck__led::after {
  content: "";
  position: absolute;
  border-radius: 50%;
  mix-blend-mode: screen;
}
/* wide, faint halo */
.deck__led::before {
  width: calc(var(--deck-w) * 0.075);
  height: calc(var(--deck-w) * 0.075);
  margin: calc(var(--deck-w) * -0.0375) 0 0 calc(var(--deck-w) * -0.0375);
  background: radial-gradient(circle, rgba(255, 70, 40, 0.55) 0, rgba(255, 60, 30, 0.22) 38%, rgba(255, 50, 20, 0) 70%);
}
/* bright core on the dot */
.deck__led::after {
  width: calc(var(--deck-w) * 0.02);
  height: calc(var(--deck-w) * 0.02);
  margin: calc(var(--deck-w) * -0.01) 0 0 calc(var(--deck-w) * -0.01);
  background: radial-gradient(circle, rgba(255, 150, 120, 0.9) 0, rgba(255, 60, 35, 0.55) 55%, rgba(255, 40, 20, 0) 100%);
}
.player.is-playing:not(.is-45) .deck__led--33, .player.is-playing.is-45 .deck__led--45 { opacity: 1; }
.player.is-playing .deck__led::before, .player.is-playing .deck__led::after { animation: led-glow 2.4s ease-in-out infinite; }
.player.is-45.is-playing .deck__led::before, .player.is-45.is-playing .deck__led::after { animation-duration: 1.78s; }   /* blinks faster at 45 */
@keyframes led-glow { 0%, 100% { opacity: 0.35; } 50% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .player.is-playing .deck__led::before, .player.is-playing .deck__led::after { animation: none; } }

/* the START/STOP key of the deck works like the play button */
.deck__button {
  position: absolute;
  left: 84.9%;
  top: 83.4%;
  width: 9.9%;
  height: 10.1%;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}
.hero .deck {
  order: -1;
  justify-self: center;
  margin-bottom: calc(var(--space-4) + 10px);
}
/* the deck is as big as possible while the text block below still fits on the same screen */
.hero {
  --deck-w: min(100vw, 980px, max(240px, calc((100vh - var(--nav-h) - var(--space-3) - 330px) * 1.296)));
  --deck-w: min(100vw, 980px, max(240px, calc((100svh - var(--nav-h) - var(--space-3) - 330px) * 1.296)));
}

/* pitch readout like on a DJ deck, below the deck, only visible while the record is held, braking or spinning up */
.tempo {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  top: calc(100% + var(--space-2));
  margin: 0;
  white-space: nowrap;
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
  color: color-mix(in srgb, var(--color-text) 48%, transparent);   /* same see-through cream as BUMMA behind the title */
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease;
}
.tempo.is-active { opacity: 1; }
.record {
  position: relative;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  /* center hole: the spindle of the deck shows through. A real spindle hole is 7.2 mm: that is 4.1 percent of a 7 inch record and 2.4 percent of a 12 inch one,
     so the hole is 4.3 percent of the record (before it was 10 percent, which looked like a thick dark ring). */
  -webkit-mask-image: radial-gradient(circle at center, transparent 0, transparent 2.05%, #000 2.25%);
  mask-image: radial-gradient(circle at center, transparent 0, transparent 2.05%, #000 2.25%);
  /* rotation is set from js/script.js: angle follows the playback position, dragging scratches */
  touch-action: none;
  cursor: grab;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  will-change: transform;
}
.record.is-grabbed { cursor: grabbing; }
/* spindle of the deck: drawn here so it sits exactly in the middle of the record hole */
.spindle {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 2.7%;
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #f4f1ea 0, #bdb7aa 45%, #5d5950 100%);
  box-shadow: 0 0 0 0.12em rgba(15, 11, 5, 0.45);
  pointer-events: none;
}
/* very faint grooves: fine rings, a slightly darker run-out and a thin ring around the hole. No gaps between tracks, the record has one song. */
.record::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  pointer-events: none;
  background:
    radial-gradient(circle, transparent 0 3.2%, rgba(15, 11, 5, 0.12) 3.5%, transparent 4.6%),
    radial-gradient(circle, transparent 0 96.5%, rgba(15, 11, 5, 0.10) 97.5%, transparent 99%),
    repeating-radial-gradient(circle, rgba(15, 11, 5, 0.045) 0 0.4%, transparent 0.4% 1.1%);
}
/* Center label: the part of a record in the middle that has no grooves and cannot be played, where the record is held. A real label is about a third
   of a 12 inch record (100 mm of 305 mm). It is a picture of printed paper (assets/deck/label-paper.webp): off-white paper with fibres, an uneven print
   (SAUDADE DO SOL, BUMMA, side A, 33 RPM, a small yellow sun printed off register), fine scratches and a little ageing at the edge. On top of it comes
   a soft shadow where it meets the grooves. The hole of the record (the mask) is cut through it. It turns with the record. */
.record::after {
  content: "";
  position: absolute;
  inset: 32%;
  border-radius: 50%;
  pointer-events: none;
  background: url("/assets/deck/label-paper.webp") center / 100% 100% no-repeat;
  box-shadow:
    0 0 0 1.5px rgba(20, 14, 6, 0.20),                       /* shadow line where the label meets the grooves */
    0 0 7px rgba(20, 14, 6, 0.24);
}
.record__img {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
  pointer-events: none;
  -webkit-user-drag: none;
}

/* Player */
.player__controls {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  max-width: 520px;
}
.btn.player__btn {
  flex: none;
  justify-content: center;
  width: 48px;
  height: 48px;
  min-height: 0;
  padding: 0;
  border: var(--line);
  border-radius: 50%;
  text-decoration: none;
}
.icon { width: 18px; height: 18px; fill: currentColor; }
.icon--pause { display: none; }
.player.is-playing .icon--play { display: none; }
.player.is-playing .icon--pause { display: block; }
.player__track { flex: 1; min-width: 0; }
.player__time {
  display: flex;
  justify-content: space-between;
  font-size: var(--fs-small);
  color: var(--color-muted);
}

/* Thin progress line instead of the default slider */
.player__seek {
  -webkit-appearance: none;
  appearance: none;
  display: block;
  width: 100%;
  height: 24px;
  margin: 0;
  background: transparent;
  cursor: pointer;
}
.player__seek::-webkit-slider-runnable-track { height: 1px; background: var(--color-text); }
.player__seek::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 9px;
  height: 9px;
  margin-top: -4px;
  background: var(--color-text);
  border: 0;
  border-radius: 50%;
}
.player__seek::-moz-range-track { height: 1px; background: var(--color-text); }
.player__seek::-moz-range-thumb {
  width: 9px;
  height: 9px;
  background: var(--color-text);
  border: 0;
  border-radius: 50%;
}

/* Home: play button, timeline and times on one level. The line is the timeline: played part solid, rest see-through. */
.hero__bar { display: flex; align-items: center; gap: var(--space-3); }
.hero__bar .player__seek { flex: 1; min-width: 0; height: 28px; }
.hero__bar .player__seek::-webkit-slider-runnable-track {
  height: 2px;
  background: linear-gradient(to right, var(--color-text) var(--p, 0%), color-mix(in srgb, var(--color-text) 35%, transparent) var(--p, 0%));
}
.hero__bar .player__seek::-webkit-slider-thumb { width: 11px; height: 11px; margin-top: -4.5px; }
.hero__bar .player__seek::-moz-range-track { height: 2px; background: color-mix(in srgb, var(--color-text) 35%, transparent); }
.hero__bar .player__seek::-moz-range-progress { height: 2px; background: var(--color-text); }
.hero__bar .player__seek::-moz-range-thumb { width: 11px; height: 11px; }
/* time in the track / length of the track */
.hero__bar .player__time {
  flex: none;
  display: flex;
  gap: 0.4em;
  justify-content: flex-start;
  font-size: var(--fs-small);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  color: var(--color-text);
}
.hero__bar .player__sep { color: color-mix(in srgb, var(--color-text) 48%, transparent); }
.hero__bar #status:empty { display: none; }

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0 var(--space-4);
}
/* phones: all platforms in one line in the middle, the type scales with the screen width so the five names always fit (same as on About) */
@media (max-width: 639px) {
  .hero__actions { flex-wrap: nowrap; gap: 0 2.4vw; }
  .hero__actions .btn { font-size: min(var(--fs-small), 2.8vw); white-space: nowrap; }
}

@media (min-width: 640px) {
  .hero {
    --deck-w: min(100vw, 980px, max(240px, calc((100vh - var(--nav-h) - var(--space-3) - 206px - 9.1vh) * 1.296)));
    --deck-w: min(100vw, 980px, max(240px, calc((100svh - var(--nav-h) - var(--space-3) - 206px - 9.1svh) * 1.296)));
  }
  .hero__title { font-size: min(var(--fs-h1), 4.75rem, 9vh, 5.8vw); font-size: min(var(--fs-h1), 4.75rem, 9svh, 5.8vw); }
}
@media (min-width: 768px) {
  /* the objects and their notes need room left and right of the deck
  .hero__inner { padding-bottom: var(--space-2); }   /* the lower part (title, timeline, links) sits closer to the bottom edge, the turntable gets the room */, so the deck is never wider than this */
  .hero {
    --deck-w: min(980px, 56vw, max(240px, calc((100vh - var(--nav-h) - var(--space-3) - 206px - 9.1vh) * 1.296)));
    --deck-w: min(980px, 56vw, max(240px, calc((100svh - var(--nav-h) - var(--space-3) - 206px - 9.1svh) * 1.296)));
  }
  /* with the table (768px and up) title, timeline and song links are exactly as wide as the turntable and centered under it */
  .hero__text, .hero__bar { width: min(var(--deck-w), 100%); justify-self: center; }
  /* the song links need more room than the turntable has on a small screen: one line, centred, as wide as it needs to be */
  .hero__actions { width: auto; max-width: 100%; justify-self: center; flex-wrap: nowrap; white-space: nowrap; }
  .hero__title { font-size: min(var(--fs-h1), 4.75rem, 9vh, 5.8vw, calc(var(--deck-w) * 0.08)); font-size: min(var(--fs-h1), 4.75rem, 9svh, 5.8vw, calc(var(--deck-w) * 0.08)); }
  .hero .deck {
    /* space between the screen edge and the deck on each side. The notes use it to stay on screen while the objects are cropped by the edge. */
    --m: calc((100vw - var(--deck-w)) / 2);
    margin-bottom: calc(var(--space-4) + 24px);
  }
}

/* Text links. Used everywhere instead of buttons. */
.btn {
  display: inline-flex;
  align-items: center;
  min-height: 48px;
  font: inherit;
  font-size: var(--fs-small);
  color: var(--color-text);
  background: none;
  border: 0;
  padding: 0;
  text-decoration: underline;
  text-underline-offset: 4px;
  text-decoration-thickness: 1px;
  cursor: pointer;
}

/* Sub pages */
.section {
  padding: calc(var(--space-6) + var(--nav-h)) var(--gutter) var(--space-6);
}
.page-title { font-size: min(var(--fs-h1), 10vh); }   /* also limited by the height of the window, so it stays smaller on low laptop screens */
.section p {
  max-width: 60ch;
  font-size: 1.125rem;
  font-weight: 300;
}

/* Link rows: text between hairlines, highlighted on hover */
.links { list-style: none; margin: 0; padding: 0; width: 100%; border-top: var(--line); }   /* the line between the play bar and the first link */
.links li { border-bottom: var(--line); }
.btn--block {
  display: flex;
  width: 100%;
  min-height: 56px;
  justify-content: space-between;
  padding: 0 var(--space-1);
  text-decoration: none;
}
.links__arrow { margin-left: var(--space-3); }

/* Socials: plain inline text links */
.socials { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--space-4); }

/* Music overview: an index of all releases, newest first. One row per release between hairlines. */
.release-list { list-style: none; margin: 0; padding: 0; border-top: var(--line-strong); }
.release-list li { border-bottom: var(--line); }
.release-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-4) 0;
  text-decoration: none;
}
.release-row__cover {
  width: clamp(88px, 22vw, min(200px, 22vh));
  height: auto;
  aspect-ratio: 1;
}
.release-row__arrow {
  width: 28px;
  height: 28px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: square;
  color: var(--color-text);
}
@media (max-width: 639px) { .release-row__arrow { width: 22px; height: 22px; } }
.release-row__text { display: grid; gap: var(--space-2); min-width: 0; }
.release-row__title {
  font-size: clamp(1.75rem, 6vw, min(3.5rem, 6vh));
  font-weight: 600;
  line-height: 0.95;
  letter-spacing: -0.05em;
}
.release-row__date {
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-muted);
}
.release-row__facts {
  display: flex;
  flex-wrap: wrap;
  gap: 0 0.5em;
  font-size: var(--fs-label);
  letter-spacing: 0.08em;
  color: var(--color-muted);
}
.release-row__facts span { white-space: nowrap; }
/* date and facts sit on one line, divided by dots */
.release-row__facts span:not(:first-child)::before { content: "\00b7"; margin-right: 0.5em; }
.release-row__facts time { font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase; }
/* phones: title and the facts under it, next to the cover. The technical facts (kHz, bit depth) are left out, they do not fit. */
@media (max-width: 639px) {
  .release-row { gap: var(--space-3); }
  .release-row__text { gap: var(--space-2); }
  .release-row__facts { font-size: 0.6875rem; letter-spacing: 0.04em; gap: 2px 0.4em; }
  .release-row__facts time { letter-spacing: 0.08em; }
  .release-row__tech { display: none; }
  /* the date on its own line, the rest below it, so no dot is left at the start of a line */
  .release-row__facts > span:first-child { flex-basis: 100%; }
  .release-row__facts > span:nth-child(2)::before { content: none; }
}

/* Release page: linktree style single column, built for phones and the Instagram bio link */
.release {
  min-height: 100vh;
  min-height: 100svh;
  padding-top: var(--nav-h);
  overflow: hidden;
}
.release__inner {
  max-width: 480px;
  margin: 0 auto;
  padding: var(--space-3) var(--space-3) var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  min-height: calc(100vh - var(--nav-h) - env(safe-area-inset-bottom, 0px));
  min-height: calc(100svh - var(--nav-h) - env(safe-area-inset-bottom, 0px));   /* the bottom strip is added by .release::after */
}
.release__cover {
  width: min(62vw, 270px);
  height: auto;
  aspect-ratio: 1;
  align-self: center;
  margin-bottom: var(--space-3);
  box-shadow: 0 14px 30px rgba(15, 11, 5, 0.28), 0 3px 8px rgba(15, 11, 5, 0.18);
}
/* desktop: the single column is a little wider and the cover a little bigger (still a phone-like column) */
@media (min-width: 768px) {
  .release__inner { max-width: 560px; }
  .release__cover { width: 320px; }
  .release__title { font-size: 2.35rem; }
}
/* the social links sit centered at the very bottom */
.release__title { font-size: clamp(1.5rem, 6.7vw, 2.1rem); margin-bottom: 0; }
/* BUMMA behind the title, same size as the title. The gap sits after the title as a margin, so when BUMMA wraps
   to the next line it starts flush left with no indent. */
.release__name { margin-right: 0.3em; }
.release__title .hero__artist { margin-left: 0; }   /* BUMMA is as big as the title, only see-through */   /* BUMMA stands behind the title in see-through cream, like on Home (.hero__artist) */


/* About page: exactly one screen, no scrolling. The portrait fills it and dissolves into the page background at the bottom. */
body.theme-about { min-height: 0; height: 100vh; height: 100svh; overflow: hidden; }
.about {
  position: relative;
  height: 100vh;
  height: 100svh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}
.about__photo {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 56% 74%; /* crops the empty sky at the top */
  -webkit-mask-image: linear-gradient(to bottom, #000 38%, transparent 92%);
  mask-image: linear-gradient(to bottom, #000 38%, transparent 92%);
}
/* on phones the photo is scaled up and anchored to the bottom, so the empty sky above the head falls off the top */
@media (max-width: 639px) {
  .about__photo {
    top: auto;
    bottom: 0;
    height: 122%;
    object-position: 56% 40%;
    -webkit-mask-image: linear-gradient(to bottom, #000 48%, transparent 94%);
    mask-image: linear-gradient(to bottom, #000 48%, transparent 94%);
  }
}
/* short phones: the paragraph needs room, so the photo moves up (the bottom of it fades out anyway) and the text is a little smaller, the face stays free */
@media (max-width: 639px) and (max-height: 760px) {
  .about__photo { bottom: 5%; }
  .about__text { font-size: 0.9375rem; line-height: 1.4; margin-bottom: var(--space-2); }
  .about .page-title { margin-bottom: var(--space-2); }
}
/* wide screens: the photo (2000 x 1778) is scaled to cover the screen and the excess is cropped. The top of the head is at 538px of the photo.
   Place the photo so the top of the head always sits at 10% of the screen height, whatever the shape of the window (clamped so no edge shows). */
@media (min-width: 640px) {
  .about__photo {
    --s: max(100vw / 2000, 100vh / 1778);
    --s: max(100vw / 2000, 100svh / 1778);
    object-position: 56% min(0px, max(calc(100vh - 1778 * var(--s)), calc(10vh - 538 * var(--s))));
    object-position: 56% min(0px, max(calc(100svh - 1778 * var(--s)), calc(10svh - 538 * var(--s))));
  }
}

/* a soft dark base behind the text, so it stays readable over the striped shirt */
.about::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 62%;
  z-index: 1;
  background: linear-gradient(to top, var(--color-paper), transparent);
  opacity: 0.8;
}
.about__inner {
  position: relative;
  z-index: 2;
  padding: 0 var(--gutter) calc(var(--space-4) + env(safe-area-inset-bottom, 0px));
}
.about .page-title { margin-bottom: var(--space-3); }
.about__text { max-width: 36rem; margin: 0 0 var(--space-3); font-size: var(--fs-body); font-weight: 300; }
.about .socials { gap: 0 var(--space-4); }
/* phones: all platforms in one line, like the contacts. The type scales with the screen width so the five names always fit. */
@media (max-width: 639px) {
  .about .socials { flex-wrap: nowrap; justify-content: center; gap: 0 2.4vw; }
  .about .socials .btn { font-size: min(var(--fs-small), 2.8vw); white-space: nowrap; }
}

@media (prefers-reduced-motion: reduce) {
  .tempo { transition: none; }
  .deck__arm.is-swinging, .deck__arm.is-slow { transition: none; }
}

.deck__key-stop { display: none; }
.player.is-playing .deck__key-play { display: none; }
.player.is-playing .deck__key-stop { display: inline; }

/* Notes on the objects of the table. Everything is positioned in percent of the deck, so it follows its size.
   A note is a black dot on the object, a short diagonal line (the elbow) and a label whose underline is the horizontal part of the line. */
.note {
  display: none;               /* tablet width and up only */
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;        /* only the object (.note__hit) takes clicks, so the deck stays usable */
  color: var(--color-text);
  text-decoration: none;
}
.note__hit { position: absolute; display: block; pointer-events: auto; }
/* the dot and the label of a note can be clicked too */
.note__dot, .note__label { pointer-events: auto; cursor: pointer; }
.note__dot {
  position: absolute;
  width: 10px;
  height: 10px;
  margin: -5px 0 0 -5px;
  box-sizing: border-box;
  border-radius: 50%;
  background: #0a0703;
  border: 2px solid var(--color-text);
}
.note__line { position: absolute; width: 0; height: 0; }
.note__line::before { content: ""; position: absolute; left: 0; top: 0; width: 28px; height: 0; border-top: 1px solid var(--color-text); transform-origin: 0 0; }
.note__label {
  position: absolute;
  /* a small dark, see-through chip with a little blur behind the text: readable on wood and on the paper of the sleeve and polaroid.
     Its bottom edge is the line that leaves the dot. */
  padding: 4px 9px 5px;
  background: rgba(28, 16, 8, 0.62);
  -webkit-backdrop-filter: blur(5px);
  backdrop-filter: blur(5px);
  border-bottom: 1px solid var(--color-text);
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.16em;
  line-height: 1.2;
  text-transform: uppercase;
  white-space: nowrap;
}
.deck__key-stop { display: none; }
.player.is-playing .deck__key-play { display: none; }
.player.is-playing .deck__key-stop { display: inline; }

@media (min-width: 768px) {
  .note { display: block; }
  /* record sleeve on the left: dot near its left edge, the line leaves to the upper left, the label sits left of the elbow */
  .note--music .note__hit { left: -40%; top: 17%; width: 40%; height: 72%; transform: rotate(-7deg); }
  /* the dot sits near the left edge of the sleeve, but never further out than the label (about 116px plus the elbow) still fits on screen */
  .note--music .note__dot, .note--music .note__line { left: max(calc(var(--deck-w) * -0.405), calc(156px - var(--m))); top: 58%; }
  .note--music .note__line::before { transform: rotate(-135deg); }
  .note--music .note__label { right: 19.8px; bottom: 19.8px; }
  /* polaroid on the right: dot near its right edge, the line leaves to the upper right, the label sits right of the elbow */
  .note--about .note__hit { left: 116%; top: 86%; width: 21%; height: 24%; transform: rotate(9deg); }
  /* the dot sits near the right edge of the polaroid, but never further out than the label (about 60px plus the elbow) still fits on screen */
  .note--about .note__dot, .note--about .note__line { left: min(calc(var(--deck-w) * 1.36), calc(var(--deck-w) + var(--m) - 100px)); top: 100%; }
  .note--about .note__line::before { transform: rotate(-45deg); }
  .note--about .note__label { left: 19.8px; bottom: 19.8px; }
  /* speed switch at the lower left of the deck: the line leaves downwards to the left, the label sits left of the elbow, above the line */
  .note--speed { --drop: calc(var(--deck-w) * 0.0748 + 24px); }   /* distance to the bottom edge of the deck plus the height of the chip and a gap, so the chip does not touch the frame */
  .note--speed .note__dot, .note--speed .note__line { left: 10.9%; top: 90.3%; }
  .note--speed .note__line::before { width: calc(var(--drop) * 1.1547); transform: rotate(120deg); }
  .note--speed .note__label { right: calc(var(--drop) * 0.5774); top: var(--drop); transform: translateY(-100%); }
  /* START/STOP key, tablets and small laptops: the line goes straight down from the key, the label sits at its end, to the right of the line. The pitch readout
     is centred under the deck and the label stays right of it. */
  .note--key { --drop: calc(var(--deck-w) * 0.0926 + 36px); }
  .note--key .note__dot, .note--key .note__line { left: 88%; top: 88%; }   /* bottom left of the black key */
  .note--key .note__line::before { width: var(--drop); transform: rotate(90deg); }
  .note--key .note__label { left: 0; right: auto; top: var(--drop); transform: translateY(-100%); }
}
/* low windows (small turntable): the polaroid is close, so the label is two short lines (START / MUSIC) and fits between the line and the polaroid */
@media (min-width: 768px) and (max-height: 800px) {
  .note--key .note__label { width: min-content; white-space: normal; text-align: left; letter-spacing: 0.1em; }
}
}
/* ABOUT, when there is no room right of the polaroid (js/script.js sets .notes-tight): the dot sits on the white strip at the bottom of the
   polaroid, a short line goes straight down and the label hangs below it, its right edge a little right of the dot, so it stays on screen
   and never lies over the photo. */
@media (min-width: 768px) {
  .hero.notes-tight .note--about .note__dot, .hero.notes-tight .note--about .note__line { left: 128%; top: 108.4%; }   /* on the bottom edge of the polaroid, below the handwriting */
  .hero.notes-tight .note--about .note__line::before { width: 26px; transform: rotate(90deg); }
  .hero.notes-tight .note--about .note__label { left: auto; right: -34px; top: 26px; bottom: auto; }
}
/* the label runs to the right only when the screen is wide AND high enough for a big turntable: the polaroid sits at a distance that grows with the turntable,
   the label has a fixed size, so on a low screen (small turntable) the label would lie over the polaroid. There the label stays below the turntable. */
@media (min-width: 1400px) and (min-height: 940px) {
  /* START/STOP key, wide screens: the line leaves downwards to the right onto the wood, the label sits above it */
  .note--key .note__dot, .note--key .note__line { left: 93%; top: 86.6%; }   /* top right of the black key */
  .note--key .note__line::before { width: 45px; transform: rotate(45deg); }   /* a longer elbow, so the label sits further to the right, clear of the frame */
  .note--key .note__label { right: auto; left: 31.8px; top: 31.8px; transform: translateY(-100%); }
}

/* Page transitions (cross-document View Transitions, Chrome, Edge and Safari 18.2+; other browsers just load the page).
   The old page slides out and the new page slides in. The direction comes from js/slide.js as a transition type: a page on the right
   (About) comes in from the right, a page on the left (All releases, release pages) comes in from the left. Home is in the middle. */
/* the slide is only for big screens with a mouse: on phones and tablets the browser showed the old page for a moment before it started */
@media (min-width: 768px) and (pointer: fine) {
  @view-transition { navigation: auto; }
}
::view-transition-old(root), ::view-transition-new(root) { animation-duration: 0.85s; animation-timing-function: cubic-bezier(0.55, 0, 0.15, 1); mix-blend-mode: normal; }
::view-transition-old(root) { animation-name: slide-out-left; }
::view-transition-new(root) { animation-name: slide-in-right; }
html:active-view-transition-type(from-left)::view-transition-old(root) { animation-name: slide-out-right; }
html:active-view-transition-type(from-left)::view-transition-new(root) { animation-name: slide-in-left; }
@keyframes slide-out-left { to { transform: translateX(-100%); } }
@keyframes slide-in-right { from { transform: translateX(100%); } }
@keyframes slide-out-right { to { transform: translateX(100%); } }
@keyframes slide-in-left { from { transform: translateX(-100%); } }
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; }
}

/* Arrows at the screen edge to go back to Home: on About to the left, on All releases to the right (the direction the pages slide in from).
   They are only there while the objects on the home page can be clicked (768px and up), on phones the menu is the way to navigate. */
.edge-arrow { display: none; }
@media (min-width: 768px) {
  .edge-arrow {
    display: flex;
    position: fixed;
    top: 50%;
    transform: translateY(-50%);
    z-index: 4;
    width: 64px;
    height: 64px;
    align-items: center;
    justify-content: center;
    color: var(--color-text);
    border: 1.5px solid currentColor;
    border-radius: 50%;
    background: color-mix(in srgb, var(--menu-tint) 28%, transparent);
    -webkit-backdrop-filter: blur(8px);
    backdrop-filter: blur(8px);
  }
  .edge-arrow svg { width: 36px; height: 36px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
  .edge-arrow--left { left: var(--space-4); }
  .edge-arrow--right { right: var(--space-4); }
  /* keep the content of All releases clear of the arrow */
  .section { padding-right: max(var(--gutter), 112px); }
}
