/* Noteion — scrapbook on a dark, layered canvas (OWARI DIARY–style immersion) */

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

:root {
  --shell-header-offset: 5.35rem;
  --shell-footer-offset: 3.25rem;
  /* Space above each album tile for corner tab controls */
  --genre-stack-controls-gap: 1.1rem;
  --void: #050506;
  --ink: #0c0c0e;
  --panel: #101014;
  --line: rgba(250, 248, 240, 0.12);
  --muted: rgba(250, 248, 240, 0.55);
  --cream: #f6f3ea;
  --paper: #ebe6dc;
  --accent: #c4a574;
  --vinyl: #121214;
  --vinyl-groove: #2a2a2e;
  --shadow: rgba(0, 0, 0, 0.45);
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  /* Two-row horizontal strip: large “album” tiles */
  --album-size: clamp(9.1rem, 22vmin, 12.5rem);
  --album-gap-row: clamp(3.7rem, 7.5vmin, 4.9rem);
  --album-gap-col: clamp(4.5rem, 8.5vmin, 6.2rem);
  /* Half-step offset so the bottom row sits between top-row albums */
  --album-stagger: calc((var(--album-size) + var(--album-gap-col)) * 0.5);
  --safe-x: env(safe-area-inset-left, 0px);
  --safe-x-right: env(safe-area-inset-right, 0px);
  --safe-y-top: env(safe-area-inset-top, 0px);
  --safe-y-bottom: env(safe-area-inset-bottom, 0px);
  --album-tab-left-inset: 0.72rem;
}

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

html,
body {
  margin: 0;
  min-height: 100%;
  font-family: var(--font-roboto);
  color: var(--cream);
  background: var(--void);
  /* Gold-accent scrollbar (Firefox + others) */
  scrollbar-color: var(--accent) rgba(12, 12, 14, 0.55);
  scrollbar-width: thin;
}

/* Subtle retro arrow cursor — gold (accent-colored) pointer with a
   black outline reminiscent of classic 90s OS cursors. Hot-spot at
   the tip (1,1). Applied to every element with !important so it
   beats the many local `cursor: pointer` declarations scattered
   across the project's CSS files. The pointer rule below switches
   to a cream-filled variant on hover over interactive elements. */
html,
body,
* {
  cursor:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20'><path d='M2 1 L2 16 L6 12 L9 18 L11.5 16.7 L8.5 11 L13.5 11 Z' fill='%23c4a574' stroke='%23070707' stroke-width='1.2' stroke-linejoin='round'/></svg>")
      1 1,
    default !important;
}

/* Hovering an interactive target (link, button, input, etc.) swaps
   the cursor to a cream-filled version of the same retro arrow so
   clickable areas read distinctly. */
a,
a *,
button,
button *,
[role="button"],
[role="button"] *,
[onclick],
[onclick] *,
.icon-btn,
.icon-btn *,
input[type="submit"],
input[type="button"],
input[type="checkbox"],
input[type="radio"],
input[type="file"],
.header-compose-btn,
.profile-new-song,
.profile-new-album,
label,
label *,
select,
summary {
  cursor:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20'><path d='M2 1 L2 16 L6 12 L9 18 L11.5 16.7 L8.5 11 L13.5 11 Z' fill='%23faf5e8' stroke='%23070707' stroke-width='1.2' stroke-linejoin='round'/></svg>")
      1 1,
    pointer !important;
}

/* No hover underline on anchors; components use color / chips instead */
a:hover {
  text-decoration: none;
}

/* Gold-accent scrollbar (WebKit / Blink: Safari, Chrome, Edge). */
*::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}
*::-webkit-scrollbar-track {
  background: rgba(12, 12, 14, 0.55);
}
*::-webkit-scrollbar-thumb {
  background-color: var(--accent);
  border-radius: 999px;
  border: 2px solid rgba(12, 12, 14, 0.55);
}
*::-webkit-scrollbar-thumb:hover {
  background-color: color-mix(in oklab, var(--accent) 80%, white 20%);
}
*::-webkit-scrollbar-corner {
  background: transparent;
}

body.is-popup-open {
  overflow: hidden;
}

.page {
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  position: relative;
}

/* —— Loading (fade like promo sites) —— */
.page-loading {
  position: fixed;
  inset: 0;
  z-index: 10000;
  background: var(--void);
  pointer-events: none;
  opacity: 1;
  transition: opacity 0.75s var(--ease-out);
}

.page-loading.is-done {
  opacity: 0;
}

/* —— Header —— */
.page-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 50;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: end;
  gap: 1rem;
  padding:
    max(1.1rem, var(--safe-y-top)) max(1.25rem, var(--safe-x-right)) 0.85rem max(1.25rem, var(--safe-x));
  border-bottom: 1px solid var(--line);
  background: linear-gradient(180deg, rgba(8, 8, 10, 0.94) 0%, rgba(8, 8, 10, 0.72) 100%);
  backdrop-filter: blur(10px);
}

.header-brand {
  min-width: 0;
  justify-self: start;
}

.logo {
  margin: 0;
  font-family: var(--font-logo);
  font-size: clamp(1.45rem, 2.7vw, 1.75rem);
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  line-height: 1.1;
}

@media (min-width: 701px) {
  .header-brand,
  .header-actions {
    transform: translateY(-3px);
  }
}

.logo a,
.logo a:visited {
  color: #ffffff;
  text-decoration: none;
}

.logo a:hover,
.logo a:focus-visible {
  color: var(--accent);
}

.header-tagline {
  margin: 0.35rem 0 0;
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  max-width: 100%;
  overflow-wrap: anywhere;
  line-height: 1.35;
}

.header-actions {
  display: flex;
  align-items: center;
  gap: 0.2rem;
  justify-self: end;
}

.header-compose-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0;
  justify-self: center;
  padding: 0.16rem;
  border-radius: 999px;
  border: 2px solid rgba(196, 165, 116, 0.62);
  background:
    repeating-linear-gradient(
      -12deg,
      rgba(255, 246, 230, 0.045) 0 2px,
      rgba(12, 12, 15, 0.08) 2px 4px
    ),
    linear-gradient(180deg, rgba(28, 24, 20, 0.94) 0%, rgba(12, 12, 16, 0.95) 100%);
  box-shadow:
    inset 0 1px 0 rgba(255, 244, 224, 0.2),
    0 0 0 1px rgba(58, 44, 24, 0.7);
}

.header-compose-btn {
  position: relative;
  overflow: hidden;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 2.2rem;
  min-width: clamp(6.25rem, 11vw, 7.75rem);
  padding: 0.32rem 0.8rem;
  border-radius: 999px;
  font-family: var(--font-rajdhani);
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  border: 1px solid rgba(40, 30, 20, 0.45);
}

.header-compose-btn::before {
  content: "";
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(
    -20deg,
    rgba(255, 255, 255, 0.08) 0 1px,
    rgba(255, 255, 255, 0) 1px 3px
  );
  mix-blend-mode: soft-light;
  pointer-events: none;
}

.header-compose-btn.profile-new-song {
  color: #1f1710;
  text-shadow: 0 1px 0 rgba(255, 246, 226, 0.5);
  background: linear-gradient(180deg, #dbc79e 0%, #c8ad7a 52%, #b59462 100%);
  border-color: rgba(106, 74, 34, 0.62);
}

.header-compose-btn.profile-new-album {
  color: rgba(250, 248, 240, 0.95);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.55);
  background: linear-gradient(180deg, rgba(34, 35, 48, 0.98) 0%, rgba(18, 20, 32, 0.98) 100%);
  border-color: rgba(165, 140, 100, 0.55);
}

.header-compose-btn:hover {
  filter: brightness(1.06);
}

.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.35rem;
  height: 2.35rem;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 50%;
  background: transparent;
  color: var(--cream);
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  text-decoration: none;
  transition:
    background 0.2s ease,
    border-color 0.2s ease,
    color 0.2s ease;
}

.icon-btn:hover {
  background: rgba(250, 248, 240, 0.06);
  border-color: var(--line);
}

.icon-btn[aria-expanded="true"],
.icon-btn[aria-current="page"] {
  background: rgba(196, 165, 116, 0.15);
  border-color: rgba(196, 165, 116, 0.35);
  color: var(--accent);
}

/* —— Main depth layers —— */
.page-main {
  position: relative;
  flex: 1;
  min-height: 0;
  padding-top: var(--shell-header-offset);
  padding-bottom: var(--shell-footer-offset);
  /* Flex item + wide inner board: allow shrinking so .board-scroll can overflow-x */
  min-width: 0;
  overflow: hidden;
}

.main-back,
.main-book,
.main-fore {
  position: absolute;
  inset: -8%;
  pointer-events: none;
  will-change: transform;
}

.main-back {
  /* Wood over void — low opacity so the page background reads through */
  background: url("assets/homepage-wood-bg.jpg") center / cover no-repeat, var(--ink);
  opacity: 0.18;
  transition: transform 0.35s ease-out;
}

.main-book {
  background: none;
  mix-blend-mode: normal;
  opacity: 0;
  transition: transform 0.45s ease-out;
}

.main-fore {
  background: transparent;
  transition: transform 0.55s ease-out;
}

.board-wrap {
  position: relative;
  z-index: 10;
  padding: 3.45rem 0 2.75rem;
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-width: 0;
  min-height: calc(100vh - 12rem);
}

.board-scroll-hint {
  position: absolute;
  right: 1rem;
  bottom: 0.5rem;
  z-index: 13;
  font-size: 0.58rem;
  font-weight: 700;
  letter-spacing: 0.35em;
  text-transform: uppercase;
  color: rgba(250, 248, 240, 0.28);
  pointer-events: none;
}

@media (min-width: 900px) {
  .board-scroll-hint {
    display: none;
  }
}

.board-wrap::before {
  content: "";
  position: absolute;
  inset: 0;
  opacity: 0.07;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

.board-scroll {
  position: relative;
  z-index: 11;
  flex: 1 1 auto;
  min-width: 0;
  padding: 2.7rem max(1rem, env(safe-area-inset-right)) 1.25rem max(1rem, env(safe-area-inset-left));
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch;
  touch-action: pan-x pinch-zoom;
  scrollbar-color: rgba(196, 165, 116, 0.45) rgba(250, 248, 240, 0.06);
  outline: none;
}

.board-scroll:focus-visible {
  box-shadow: inset 0 0 0 2px rgba(196, 165, 116, 0.35);
  border-radius: 4px;
}

.scrapbook-board {
  position: relative;
  z-index: 11;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--album-gap-row);
  width: max-content;
  min-height: calc(2 * (var(--album-size) + var(--genre-stack-controls-gap)) + var(--album-gap-row));
  padding: 0.35rem var(--album-stagger) 1rem 3.4rem;
  margin: 0;
}

.scrapbook-row {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  align-items: center;
  gap: var(--album-gap-col);
  width: max-content;
}

.scrapbook-row--bottom {
  margin-inline-start: var(--album-stagger);
}

.genre-card {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  width: fit-content;
  max-width: 100%;
  height: auto;
  flex-shrink: 0;
  perspective: 500px;
  cursor: pointer;
  transition:
    transform 0.35s var(--ease-out),
    z-index 0s;
  scroll-margin: 5rem max(1rem, env(safe-area-inset-left)) 3rem max(1rem, env(safe-area-inset-right));
}

/* Frame around stack; bottom “wood crate” front matches icon: 3 slats + posts + nails */
.genre-crate {
  position: relative;
  flex-shrink: 0;
  z-index: 1;
  isolation: isolate;
  padding: 0.35rem 0.48rem 0.52rem;
  border-radius: 0.16rem;
  border: none;
  background: transparent;
  box-shadow: none;
}

.genre-crate-feet {
  position: absolute;
  z-index: 12;
  left: 0.38rem;
  right: 0.38rem;
  bottom: 0.3rem;
  display: flex;
  flex-direction: row;
  align-items: stretch;
  height: clamp(6.25rem, 52%, 8.75rem);
  max-height: calc(var(--album-size) * 0.78);
  pointer-events: none;
}

.genre-crate-post {
  flex: 0 0 0.48rem;
  align-self: stretch;
  background: #0c0c0e;
  border-radius: 0.05rem;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.45);
}

.genre-crate-post--left {
  margin-right: 0.06rem;
}

.genre-crate-post--right {
  margin-left: 0.06rem;
}

.genre-crate-slats {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  padding: 0;
  background: transparent;
  border-radius: 0;
  box-shadow: none;
}

.genre-crate-slat {
  flex: 1 1 0;
  min-height: 1.45rem;
  position: relative;
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  padding: 0 0.32rem;
  background: #0a0a0c;
  border-radius: 0.08rem;
  border: 1px solid rgba(0, 0, 0, 0.75);
  box-shadow:
    inset 0 1px 0 rgba(58, 60, 66, 0.45),
    0 0 0 1px rgba(72, 76, 84, 0.35);
}

.genre-crate-nail {
  flex-shrink: 0;
  width: 0.56rem;
  height: 0.56rem;
  border-radius: 50%;
  background: linear-gradient(145deg, #4a4e56 0%, #2a2c32 100%);
  box-shadow:
    inset 0 1px 0 rgba(72, 76, 84, 0.35),
    0 0 0 1px rgba(0, 0, 0, 0.55);
  position: relative;
}

.genre-crate-nail::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0.16rem;
  height: 0.16rem;
  margin: -0.08rem 0 0 -0.08rem;
  border-radius: 50%;
  background: #0c0c0e;
}

/* Home board only: hide the decorative dark “crate front” (slats + posts). Cratedigger 3D crates stay as-is. */
#genre-board .genre-crate-feet {
  display: none !important;
}

.genre-card-controls {
  position: absolute;
  top: -1.52rem;
  left: 50%;
  width: var(--album-size);
  min-height: 0;
  margin: 0;
  z-index: 18;
  transform: translateX(-50%) rotate(var(--tilt, 0deg));
  transform-origin: center bottom;
  pointer-events: none;
}

.genre-card-controls .stack-shuffle {
  pointer-events: auto;
}

.genre-card.is-spotlight {
  animation: card-pulse 1.1s var(--ease-out) 1;
}

@keyframes card-pulse {
  0%,
  100% {
    filter: none;
  }
  40% {
    filter: drop-shadow(0 0 12px rgba(196, 165, 116, 0.55));
  }
}

.genre-card:hover:not(:has(.stack-shuffle:hover)),
.genre-card:focus-within:not(:has(.stack-shuffle :focus)) {
  z-index: 20;
  transform: scale(1.07);
}

.card-inner {
  position: relative;
  width: var(--album-size);
  height: var(--album-size);
  flex-shrink: 0;
  transform: rotate(var(--tilt, 0deg));
  transition: transform 0.4s var(--ease-out);
  isolation: isolate;
}

/* Extra “cards” behind the face — stacked scrapbook look */
.card-inner::before,
.card-inner::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--paper);
  border: 1px solid rgba(0, 0, 0, 0.07);
  box-shadow:
    1px 2px 0 rgba(0, 0, 0, 0.1),
    3px 10px 20px rgba(0, 0, 0, 0.32);
  pointer-events: none;
  transition:
    transform 0.38s var(--ease-out),
    opacity 0.3s ease;
}

.card-inner::before {
  z-index: 0;
  opacity: 0.93;
}

.card-inner::after {
  z-index: 1;
  opacity: 0.96;
}

/* Stack presets — shuffle via [data-stack-arr] on .card-inner */
.card-inner[data-stack-arr="0"]::before {
  transform: rotate(-4.5deg) translate(6px, 8px);
}
.card-inner[data-stack-arr="0"]::after {
  transform: rotate(3.5deg) translate(3px, 4px);
}

.card-inner[data-stack-arr="1"]::before {
  transform: rotate(5deg) translate(-4px, 6px);
}
.card-inner[data-stack-arr="1"]::after {
  transform: rotate(-3deg) translate(5px, 5px);
}

.card-inner[data-stack-arr="2"]::before {
  transform: rotate(-2deg) translate(8px, 3px);
}
.card-inner[data-stack-arr="2"]::after {
  transform: rotate(6deg) translate(-2px, 8px);
}

.card-inner[data-stack-arr="3"]::before {
  transform: rotate(4deg) translate(5px, -3px);
}
.card-inner[data-stack-arr="3"]::after {
  transform: rotate(-5deg) translate(6px, 7px);
}

/* Community album art on the rearmost scrapbook square; shuffle cycles layouts + cover when multiple */
/* Duotone: art supplies luminance (reads like greyscale), solid genre color supplies hue/sat (understated) */
.card-inner[data-has-board-cover="1"]::before {
  background:
    var(--board-cover-next, var(--board-cover)) center / cover no-repeat,
    linear-gradient(
      0deg,
      var(--genre-overlay, hsl(36, 36%, 54%)),
      var(--genre-overlay, hsl(36, 36%, 54%))
    ),
    var(--paper);
  background-blend-mode: luminosity, normal;
  border: 1px solid rgba(0, 0, 0, 0.07);
  opacity: 0.97;
}

.card-inner[data-has-board-cover="1"]::after {
  background:
    var(--board-cover-third, var(--board-cover-next, var(--board-cover))) center / cover no-repeat,
    linear-gradient(
      0deg,
      var(--genre-overlay, hsl(36, 36%, 54%)),
      var(--genre-overlay, hsl(36, 36%, 54%))
    ),
    var(--paper);
  background-blend-mode: luminosity, normal;
}

.genre-card:hover:not(:has(.stack-shuffle:hover)) .card-inner,
.genre-card:focus-within:not(:has(.stack-shuffle :focus)) .card-inner {
  transform: rotate(0deg) translateY(-2px);
}

.card-face {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 0.5rem;
  background: var(--paper);
  color: #1a1917;
  border: 1px solid rgba(0, 0, 0, 0.08);
  box-shadow:
    2px 3px 0 rgba(0, 0, 0, 0.12),
    6px 14px 24px var(--shadow);
  transition:
    opacity 0.3s var(--ease-out),
    transform 0.3s var(--ease-out);
}

.card-face[data-has-face-cover="1"] {
  background:
    var(--face-cover) center / cover no-repeat,
    linear-gradient(
      0deg,
      var(--genre-overlay, hsl(36, 36%, 54%)),
      var(--genre-overlay, hsl(36, 36%, 54%))
    ),
    var(--paper);
  background-blend-mode: luminosity, normal;
  color: #f8f6f1;
}

.card-face[data-has-face-cover="1"] .genre-rank {
  color: rgba(248, 246, 241, 0.82);
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.55);
}

.card-face[data-has-face-cover="1"] .genre-name {
  text-shadow:
    0 2px 8px rgba(0, 0, 0, 0.65),
    0 0 1px rgba(0, 0, 0, 0.45);
}

/* Album-corner tab controls */
.stack-shuffle {
  position: relative;
  --stack-rise-offset: 0rem;
  z-index: 6;
  display: flex;
  width: auto;
  align-items: center;
  justify-content: flex-start;
  gap: 0.22rem;
  padding: 0 0 0 var(--album-tab-left-inset);
  overflow: visible;
  pointer-events: auto;
  background: none;
  border: none;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.28));
  transform: translateY(var(--stack-rise-offset));
  transition:
    transform 0.22s var(--ease-out),
    filter 0.22s var(--ease-out),
    opacity 0.3s var(--ease-out);
}

/* Keep data-driven variation but subtle for tabs */
.stack-shuffle[data-stack-rise="0"] {
  --stack-rise-offset: 0rem;
}
.stack-shuffle[data-stack-rise="1"] {
  --stack-rise-offset: 0.02rem;
}
.stack-shuffle[data-stack-rise="2"] {
  --stack-rise-offset: -0.01rem;
}
.stack-shuffle[data-stack-rise="3"] {
  --stack-rise-offset: 0.03rem;
}
.stack-shuffle[data-stack-rise="4"] {
  --stack-rise-offset: 0.01rem;
}
.stack-shuffle[data-stack-rise="5"] {
  --stack-rise-offset: 0.04rem;
}
.stack-shuffle[data-stack-rise="6"] {
  --stack-rise-offset: 0.02rem;
}
.stack-shuffle[data-stack-rise="7"] {
  --stack-rise-offset: 0.03rem;
}

.stack-shuffle:hover {
  filter: drop-shadow(3px 8px 16px rgba(0, 0, 0, 0.5));
}

.stack-shuffle-btn {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 1.9rem;
  height: 1.55rem;
  min-width: 1.9rem;
  padding: 0;
  margin: 0;
  border-width: 1px;
  border-style: solid;
  border-color: rgba(248, 244, 234, 0.86);
  border-radius: 0.52rem 0.52rem 0.12rem 0.12rem;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.35) 0%, rgba(255, 255, 255, 0.08) 100%),
    linear-gradient(180deg, var(--genre-overlay, hsl(36, 36%, 54%)) 0%, color-mix(in oklab, var(--genre-overlay, hsl(36, 36%, 54%)), black 14%) 100%);
  color: rgba(250, 248, 240, 0.98);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.45),
    0 1px 0 rgba(0, 0, 0, 0.2);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
  transition:
    transform 0.2s var(--ease-out),
    box-shadow 0.2s ease,
    filter 0.2s ease;
}

.stack-shuffle-btn::before {
  display: none;
}

.stack-shuffle-btn::after {
  display: none;
}

.stack-shuffle[data-sticker="1"] .stack-shuffle-btn::before {
  mix-blend-mode: normal;
  opacity: 0.42;
}

.stack-shuffle-btn:first-child {
  transform: rotate(-1.4deg);
  z-index: 1;
}

.stack-shuffle-btn:last-child {
  transform: rotate(1.4deg);
  z-index: 2;
}

.stack-shuffle-icon {
  position: relative;
  z-index: 3;
  display: block;
  width: 0.78rem;
  height: 0.78rem;
}

/* 0 — Navy + warm white ring (bold street sticker) */
.stack-shuffle[data-sticker="0"] .stack-shuffle-btn {
  border-color: #f4efe6;
  background: radial-gradient(circle at 36% 30%, #2f6ea8 0%, #1a4a78 42%, #0c2848 100%);
  color: #faf8f4;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.2) inset,
    0 -4px 12px rgba(0, 0, 0, 0.35) inset,
    0 0 0 1px rgba(0, 0, 0, 0.35);
}

/* 1 — White disc, black ring (high contrast) */
.stack-shuffle[data-sticker="1"] .stack-shuffle-btn {
  border-color: #141414;
  background: radial-gradient(circle at 40% 35%, #ffffff 0%, #f0ebe3 70%, #e4ddd4 100%);
  color: #111;
  box-shadow:
    0 2px 0 rgba(255, 255, 255, 0.95) inset,
    0 -3px 10px rgba(0, 0, 0, 0.12) inset,
    0 0 0 1px rgba(0, 0, 0, 0.25);
}

/* 2 — Black disc, off-white ring */
.stack-shuffle[data-sticker="2"] .stack-shuffle-btn {
  border-color: #ece8e0;
  background: radial-gradient(circle at 38% 32%, #2a2a2a 0%, #121212 55%, #070707 100%);
  color: #f2efe8;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.12) inset,
    0 -5px 14px rgba(0, 0, 0, 0.55) inset,
    0 0 0 1px rgba(255, 255, 255, 0.06);
}

/* 3 — Taxi yellow */
.stack-shuffle[data-sticker="3"] .stack-shuffle-btn {
  border-color: #181818;
  background: radial-gradient(circle at 35% 30%, #ffe066 0%, #f5c933 45%, #e0b020 100%);
  color: #141414;
  box-shadow:
    0 2px 0 rgba(255, 255, 255, 0.45) inset,
    0 -3px 10px rgba(120, 90, 0, 0.25) inset,
    0 0 0 1px rgba(0, 0, 0, 0.35);
}

/* 4 — Red + white ring */
.stack-shuffle[data-sticker="4"] .stack-shuffle-btn {
  border-color: #f8f4ee;
  background: radial-gradient(circle at 38% 32%, #e64a3d 0%, #c43328 48%, #8f221a 100%);
  color: #fff8f6;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.25) inset,
    0 -4px 12px rgba(0, 0, 0, 0.35) inset,
    0 0 0 1px rgba(0, 0, 0, 0.3);
}

/* 5 — Royal blue + white ring */
.stack-shuffle[data-sticker="5"] .stack-shuffle-btn {
  border-color: #f2f0eb;
  background: radial-gradient(circle at 36% 30%, #3b5bdb 0%, #2438a8 50%, #152566 100%);
  color: #fafbff;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.22) inset,
    0 -4px 12px rgba(0, 0, 0, 0.4) inset,
    0 0 0 1px rgba(0, 0, 0, 0.35);
}

/* Match sticker arrows to each genre's album tint color */
.genre-card .stack-shuffle[data-sticker] .stack-shuffle-btn {
  border-color: rgba(248, 244, 234, 0.86);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.34) 0%, rgba(255, 255, 255, 0.07) 100%),
    linear-gradient(180deg, var(--genre-overlay, hsl(36, 36%, 54%)) 0%, color-mix(in oklab, var(--genre-overlay, hsl(36, 36%, 54%)), black 14%) 100%);
  color: rgba(250, 248, 240, 0.98);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.45),
    0 1px 0 rgba(0, 0, 0, 0.2);
}

.stack-shuffle-btn:hover {
  filter: brightness(1.08);
}

.stack-shuffle-btn:first-child:hover {
  transform: rotate(-1.4deg) translateY(0.06rem) scale(1.02);
}

.stack-shuffle-btn:last-child:hover {
  transform: rotate(1.4deg) translateY(0.06rem) scale(1.02);
}

.stack-shuffle-btn:focus-visible {
  outline: none;
  box-shadow:
    0 0 0 2px rgba(250, 248, 240, 0.95),
    0 0 0 4px rgba(196, 165, 116, 0.85);
}

.stack-shuffle-btn:active {
  filter: brightness(0.94);
}

.stack-shuffle-btn:first-child:active {
  transform: rotate(-1.4deg) translateY(0.14rem) scale(0.985);
}

.stack-shuffle-btn:last-child:active {
  transform: rotate(1.4deg) translateY(0.14rem) scale(0.985);
}

.genre-rank {
  position: absolute;
  top: 0.45rem;
  left: 0.5rem;
  font-size: clamp(0.62rem, 1.65vmin, 0.7rem);
  font-weight: 800;
  color: rgba(0, 0, 0, 0.38);
  letter-spacing: 0.02em;
}

.genre-name {
  font-size: clamp(0.92rem, 2.6vmin, 1.18rem);
  font-weight: 700;
  line-height: 1.15;
  text-transform: capitalize;
}

/* Vinyl */
.vinyl-wrap {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transform: scale(0.82);
  pointer-events: none;
  transition:
    opacity 0.3s var(--ease-out),
    transform 0.3s var(--ease-out);
}

.genre-card:hover:not(:has(.stack-shuffle:hover)) .vinyl-wrap,
.genre-card:focus-within:not(:has(.stack-shuffle :focus)) .vinyl-wrap {
  opacity: 1;
  transform: scale(1);
  pointer-events: auto;
}

.genre-card:hover:not(:has(.stack-shuffle:hover)) .card-face,
.genre-card:focus-within:not(:has(.stack-shuffle :focus)) .card-face {
  opacity: 0;
  transform: scale(0.9);
}

/* Hide backing squares + shuffle chip while vinyl preview shows (not when using shuffle arrows) */
.genre-card:hover:not(:has(.stack-shuffle:hover)) .card-inner::before,
.genre-card:hover:not(:has(.stack-shuffle:hover)) .card-inner::after,
.genre-card:focus-within:not(:has(.stack-shuffle :focus)) .card-inner::before,
.genre-card:focus-within:not(:has(.stack-shuffle :focus)) .card-inner::after {
  opacity: 0;
}

.genre-card:hover:not(:has(.stack-shuffle:hover)) .stack-shuffle,
.genre-card:focus-within:not(:has(.stack-shuffle :focus)) .stack-shuffle {
  opacity: 1;
  pointer-events: auto;
}

.vinyl {
  width: calc(var(--album-size) * 0.92);
  height: calc(var(--album-size) * 0.92);
  border-radius: 50%;
  /* Label on top; then specular arcs + radial “catch” lines (rotate with the disc); then groove rings */
  background:
    radial-gradient(
      circle at 50% 50%,
      color-mix(in oklab, var(--genre-overlay, hsl(36, 36%, 54%)), white 74%) 0 11%,
      transparent 11.5% 100%
    ),
    conic-gradient(
      from 205deg,
      transparent 0deg 26deg,
      rgba(214, 232, 255, 0.08) 32deg,
      rgba(214, 232, 255, 0.038) 42deg,
      transparent 50deg 151deg,
      rgba(214, 232, 255, 0.072) 161deg,
      rgba(214, 232, 255, 0.03) 171deg,
      transparent 176deg 250deg,
      rgba(214, 232, 255, 0.068) 255deg,
      rgba(214, 232, 255, 0.028) 265deg,
      transparent 270deg 360deg
    ),
    repeating-conic-gradient(
      from 12deg,
      transparent 0 12.5deg,
      rgba(250, 248, 240, 0.02) 12.5deg 13.15deg
    ),
    repeating-radial-gradient(
      circle at 50% 50%,
      #0e0e10 0 2px,
      #3a3a42 2px 3px
    ),
    radial-gradient(
      circle at 50% 50%,
      color-mix(in oklab, var(--genre-overlay, hsl(36, 36%, 54%)), black 62%) 0%,
      color-mix(in oklab, var(--genre-overlay, hsl(36, 36%, 54%)), black 74%) 60%,
      color-mix(in oklab, var(--genre-overlay, hsl(36, 36%, 54%)), black 86%) 100%
    );
  box-shadow:
    inset 0 0 0 3px #0a0a0c,
    0 0 0 1px rgba(250, 248, 240, 0.08),
    4px 16px 28px var(--shadow);
}

.vinyl.spinning {
  animation: vinyl-spin 2.8s linear infinite;
}

@keyframes vinyl-spin {
  to {
    transform: rotate(360deg);
  }
}

.genre-card:focus {
  outline: none;
}

.genre-card:focus-visible .card-face {
  box-shadow:
    2px 3px 0 rgba(0, 0, 0, 0.12),
    6px 14px 24px var(--shadow),
    0 0 0 3px rgba(196, 165, 116, 0.85);
}

/* —— Footer —— */
.page-footer {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 50;
  padding: 0.95rem max(1.25rem, var(--safe-x-right)) max(1.35rem, calc(0.7rem + var(--safe-y-bottom))) max(
    1.25rem,
    var(--safe-x)
  );
  border-top: 1px solid var(--line);
  background: linear-gradient(0deg, rgba(5, 5, 6, 0.98) 0%, rgba(5, 5, 6, 0.88) 100%);
}

.footer-sns {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 1rem;
}

.sns-chip {
  font-size: 0.68rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--muted);
  padding: 0.12rem 0;
  border-bottom: 1px solid transparent;
  transition:
    color 0.2s ease,
    border-color 0.2s ease;
}

.sns-chip:hover {
  color: var(--accent, #c4a574);
  text-decoration: none;
  border-bottom-color: transparent;
}

/* —— Setlist popup —— */
.page-setlist {
  position: fixed;
  inset: 0;
  z-index: 9000;
  display: grid;
  place-items: stretch;
  padding: 0;
  visibility: hidden;
  pointer-events: none;
  transition: visibility 0s linear 0.55s;
}

.page-setlist.is-open {
  visibility: visible;
  pointer-events: auto;
  transition-delay: 0s;
}

.setlist-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(3, 3, 4, 0.72);
  backdrop-filter: blur(6px);
  opacity: 0;
  transition: opacity 0.45s var(--ease-out);
}

.page-setlist.is-open .setlist-backdrop {
  opacity: 1;
}

.setlist-panel {
  position: relative;
  justify-self: end;
  width: min(26rem, 100%);
  height: 100%;
  max-height: 100dvh;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--panel);
  border-left: 1px solid var(--line);
  box-shadow: -24px 0 48px var(--shadow);
  transform: translateX(100%);
  transition: transform 0.55s var(--ease-out);
}

.page-setlist.is-open .setlist-panel {
  transform: translateX(0);
}

.setlist-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior-y: contain;
  padding: max(2rem, calc(1rem + env(safe-area-inset-top, 0px))) max(1.35rem, env(safe-area-inset-right, 0px)) 1.25rem
    max(1.35rem, env(safe-area-inset-left, 0px));
  -webkit-overflow-scrolling: touch;
}

.setlist-heading {
  margin: 0;
  font-size: 0.78rem;
  font-weight: 800;
  letter-spacing: 0.35em;
  text-transform: uppercase;
  color: var(--accent);
}

.setlist-lede {
  margin: 0.75rem 0 1.25rem;
  font-size: 0.82rem;
  line-height: 1.55;
  color: var(--muted);
}

.setlist-list {
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: track;
}

.setlist-list li {
  counter-increment: track;
  border-top: 1px solid var(--line);
}

.setlist-list li:last-child {
  border-bottom: 1px solid var(--line);
}

.setlist-list button {
  width: 100%;
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  padding: 0.85rem 0;
  border: none;
  background: transparent;
  color: var(--cream);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: color 0.2s ease;
}

.setlist-list button::before {
  content: counter(track, decimal-leading-zero);
  font-size: 0.65rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  color: var(--muted);
  min-width: 1.5rem;
}

.setlist-list button:hover,
.setlist-list button:focus-visible {
  color: var(--accent);
  outline: none;
}

.setlist-close {
  flex-shrink: 0;
  margin-top: auto;
  padding: 1rem max(1.25rem, env(safe-area-inset-right)) max(1.35rem, calc(0.75rem + env(safe-area-inset-bottom)))
    max(1.25rem, env(safe-area-inset-left));
  border: none;
  border-top: 1px solid var(--line);
  background: linear-gradient(0deg, rgba(16, 16, 20, 0.98), rgba(16, 16, 20, 0.92));
  color: var(--cream);
  cursor: pointer;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  transition:
    color 0.2s ease,
    background 0.2s ease;
}

.setlist-close:hover {
  color: var(--accent);
}

.setlist-close-text {
  display: block;
  text-align: center;
}

/* —— Lyrics search drawer (home) —— */
.page-lyrics-search {
  position: fixed;
  inset: 0;
  z-index: 9000;
  display: grid;
  place-items: stretch;
  padding: 0;
  visibility: hidden;
  pointer-events: none;
  transition: visibility 0s linear 0.55s;
}

.page-lyrics-search.is-open {
  visibility: visible;
  pointer-events: auto;
  transition-delay: 0s;
}

.lyrics-search-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(3, 3, 4, 0.72);
  backdrop-filter: blur(6px);
  opacity: 0;
  transition: opacity 0.45s var(--ease-out);
}

.page-lyrics-search.is-open .lyrics-search-backdrop {
  opacity: 1;
}

.lyrics-search-panel {
  position: relative;
  justify-self: end;
  width: min(26rem, 100%);
  height: 100%;
  max-height: 100dvh;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--panel);
  border-left: 1px solid var(--line);
  box-shadow: -24px 0 48px var(--shadow);
  transform: translateX(100%);
  transition: transform 0.55s var(--ease-out);
}

.page-lyrics-search.is-open .lyrics-search-panel {
  transform: translateX(0);
}

.lyrics-search-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior-y: contain;
  padding: max(2rem, calc(1rem + env(safe-area-inset-top, 0px))) max(1.35rem, env(safe-area-inset-right, 0px)) 1.25rem
    max(1.35rem, env(safe-area-inset-left, 0px));
  -webkit-overflow-scrolling: touch;
}

.lyrics-search-label {
  display: block;
  margin: 1rem 0 0.35rem;
  font-size: 0.65rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
}

.lyrics-search-input {
  width: 100%;
  box-sizing: border-box;
  padding: 0.65rem 0.75rem;
  font: inherit;
  font-size: 0.95rem;
  color: var(--cream);
  background: rgba(8, 8, 10, 0.65);
  border: 1px solid var(--line);
  border-radius: 6px;
}

.lyrics-search-input:focus {
  outline: 2px solid rgba(196, 165, 116, 0.45);
  outline-offset: 1px;
}

.lyrics-search-actions {
  margin-top: 1.25rem;
}

.lyrics-search-actions--split {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.lyrics-search-submit {
  width: 100%;
  padding: 0.75rem 1rem;
  font: inherit;
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--void, #050506);
  background: var(--accent);
  border: none;
  border-radius: 6px;
  cursor: pointer;
  touch-action: manipulation;
}

.lyrics-search-submit--ghost {
  color: var(--cream);
  background: transparent;
  border: 1px solid var(--line);
}

.lyrics-search-submit--ghost:hover {
  filter: none;
  border-color: rgba(196, 165, 116, 0.45);
  background: rgba(250, 248, 240, 0.06);
}

.lyrics-search-submit:not(.lyrics-search-submit--ghost):hover {
  filter: brightness(1.06);
}

.lyrics-search-results {
  margin-top: 1.35rem;
  padding-top: 1.15rem;
  border-top: 1px solid var(--line);
}

.lyrics-search-results-song {
  margin: 0 0 0.5rem;
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--cream);
  line-height: 1.35;
}

.lyrics-search-results-count {
  margin: 0 0 0.85rem;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--muted);
  line-height: 1.4;
}

.lyrics-search-posts {
  list-style: none;
  margin: 0;
  padding: 0;
}

.lyrics-search-post-item {
  margin: 0;
  padding: 0;
  border-bottom: 1px solid rgba(250, 248, 240, 0.08);
}

.lyrics-search-post-item:last-child {
  border-bottom: none;
}

.lyrics-search-post-item--clickable {
  cursor: pointer;
  border-radius: 6px;
  margin: 0 -0.35rem;
  padding: 0.2rem 0.35rem;
  transition: background 0.15s ease;
}

.lyrics-search-post-item--clickable:hover {
  background: rgba(250, 248, 240, 0.06);
}

.lyrics-search-post-item--clickable:focus-visible {
  outline: 2px solid var(--accent, #c4a574);
  outline-offset: 2px;
}

.lyrics-search-post-row {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0.35rem;
  padding: 0.55rem 0;
}

.lyrics-search-post-track {
  font-size: 0.8rem;
  font-weight: 600;
  line-height: 1.35;
  color: var(--cream, #f6f3ea);
  min-width: 0;
}

.lyrics-search-post-bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-start;
  gap: 0.5rem 0.75rem;
}

.lyrics-search-post-by {
  font-size: 0.78rem;
  line-height: 1.35;
  color: rgba(250, 248, 240, 0.82);
  min-width: 0;
}

.lyrics-search-post-genre {
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
}

.lyrics-search-post-genre:hover {
  text-decoration: none;
  color: rgba(250, 248, 240, 1);
}

/* Publisher display name — accent gold, no underline */
.lyrics-search-post-profile-link {
  color: var(--accent, #c4a574);
  font-weight: 600;
  text-decoration: none;
  border-bottom: none;
  text-transform: none;
}

.lyrics-search-post-profile-link:hover {
  color: color-mix(in oklab, var(--accent, #c4a574) 78%, var(--cream, #f6f3ea) 22%);
  text-decoration: none;
}

.lyrics-search-post-artist-link {
  color: inherit;
  font-weight: 600;
  text-decoration: none;
  border-bottom: none;
  text-transform: none;
}

.lyrics-search-post-artist-link:hover {
  color: var(--cream);
  text-decoration: none;
}

.lyrics-search-post-unavail {
  flex-shrink: 0;
  font-size: 0.65rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

@media (hover: none) and (pointer: coarse) {
  .icon-btn {
    width: 2.75rem;
    height: 2.75rem;
  }
}

@media (max-width: 700px) {
  :root {
    --shell-header-offset: 7.3rem;
  }

  /* Two-row layout on mobile:
       Row 1: title (left)  ·  icons (right)   ← inline together
       Row 2: NEW SONG / NEW ALBUM toggle (full width) */
  .page-header {
    grid-template-columns: minmax(0, 1fr) auto !important;
    grid-template-areas:
      "brand   actions"
      "toggle  toggle" !important;
    align-items: center !important;
    row-gap: 0.6rem;
  }

  .header-brand {
    grid-area: brand !important;
    justify-self: start !important;
  }

  .header-actions {
    grid-area: actions !important;
    align-self: center !important;
    justify-self: end !important;
    margin-top: 0 !important;
  }

  .header-compose-toggle {
    grid-area: toggle !important;
    width: 100% !important;
    max-width: 100% !important;
    justify-self: stretch !important;
  }

  .header-compose-btn {
    min-width: 0;
    width: 50%;
  }

  .board-wrap {
    min-height: auto;
    padding-bottom: 1.5rem;
  }

  :root {
    --album-gap-col: clamp(1.35rem, 4.2vmin, 3rem);
    --album-gap-row: clamp(1.35rem, 3.8vmin, 2.6rem);
  }

  /* Center the streaming-app chips (Spotify · Apple Music · YouTube) in
     the footer on mobile so they read as a centered row instead of
     hugging the left safe-area inset. */
  .footer-sns {
    justify-content: center;
    text-align: center;
  }
}

@media (prefers-reduced-motion: reduce) {
  .vinyl.spinning {
    animation: none;
  }

  .genre-card,
  .card-inner,
  .card-face,
  .vinyl-wrap {
    transition: none;
  }

  .card-inner::before,
  .card-inner::after {
    transition: none;
  }

  .stack-shuffle,
  .stack-shuffle-btn {
    transition: none;
  }

  .stack-shuffle-btn:first-child:hover,
  .stack-shuffle-btn:first-child:active {
    transform: rotate(-3deg);
    filter: none;
  }

  .stack-shuffle-btn:last-child:hover,
  .stack-shuffle-btn:last-child:active {
    transform: rotate(3deg);
    filter: none;
  }

  .main-back,
  .main-book,
  .main-fore {
    transition: none !important;
    transform: none !important;
  }

  .page-loading {
    transition: opacity 0.3s ease;
  }

  .page-setlist.is-open .setlist-backdrop {
    opacity: 1;
  }

  .page-setlist.is-open .setlist-panel {
    transform: none;
  }

  .genre-card.is-spotlight {
    animation: none;
  }
}

/* —— Record-store shelf (home page) ———————————————————————————————
   Honey-maple wood cubbies with an angled front lip, records leaning
   back inside each cubby. Inspired by a real record-store display. */

:root {
  --shelf-album-size: clamp(6.8rem, 16vmin, 9.5rem);
  --shelf-bin-pad-x: 0.35rem;
  --shelf-wall-thickness: 0.55rem;
  --shelf-bin-width: calc(var(--shelf-album-size) + var(--shelf-bin-pad-x) * 2 + var(--shelf-wall-thickness));
  --shelf-lip-height: 4.25rem;
  --shelf-top-height: 0.6rem;
  --shelf-base-height: 0.7rem;
  --shelf-album-tilt: 14deg;

  /* Honey / maple wood palette, matching the reference photograph. */
  --wood-hi: #f1c88a;
  --wood-mid: #d9a35b;
  --wood-mid-dark: #b8843e;
  --wood-lo: #8a5b25;
  --wood-shadow: #5b3814;
  --wood-ink: #3a2410;

  /* Photographic wood texture shared with the crate page so the home
     shelves and the 3D crate feel like the same material. */
  --wood-texture: url("cratedigger-lib/images/wood.jpg");

  --label-paper: #f8efd8;
  --label-paper-dark: #e6d9b2;
  --label-ink: #2a1d0c;
}

/* Dim the page wood backdrop — the shelf itself is the foreground now.
   Bottom stop matches the footer (#050506) so there's no visible grey
   band between the shelf base and the footer. */
.main-back {
  background: linear-gradient(180deg, #1a1a1d 0%, #050506 100%);
  opacity: 1;
}

.board-scroll-hint {
  display: none;
}

.board-wrap {
  padding: 1rem 0 10.25rem;
  min-height: 0;
}

/* Shelf fits within the viewport — no vertical scrolling. The chain
   of flex containers (.page-main → .board-wrap → .board-scroll →
   #genre-board) all fill available height, and the grid uses
   aspect-ratio so it scales down to fit both axes. */
.page-main {
  overflow: hidden;
}

/* Lock the home shelf to the viewport on desktop so the page never
   scrolls vertically. Scoped via :has(#genre-board) so it only
   applies to the home page; other pages keep their normal scroll.
   Breakpoint is 901px+ to match the mobile/tablet shelf reflow at
   max-width: 900px below — otherwise tablets would inherit the
   desktop overflow lock and lose vertical scroll. */
@media (min-width: 901px) {
  html:has(#genre-board),
  body:has(#genre-board) {
    overflow: hidden;
    height: 100%;
    height: 100dvh;
    overscroll-behavior: none;
  }

  .page:has(#genre-board) {
    height: 100vh;
    height: 100dvh;
    min-height: 0;
    max-height: 100dvh;
    overflow: hidden;
  }
}

/* Top/bottom padding stays constant; the left/right padding is 0
   because the grid auto-centers itself with `margin: 0 auto` and its
   left/right breathing room grows/shrinks with the viewport to keep
   cubbies square. */
.board-scroll {
  padding: 2rem 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  touch-action: pan-y pinch-zoom;
}

@media (max-width: 700px) {
  .board-wrap {
    padding: 1rem 0 6.5rem;
  }
  .board-scroll {
    padding: 1.5rem 0;
  }
}

/* No horizontal scrolling anymore — hide the "scroll" corner hint. */
.board-scroll-hint {
  display: none;
}

/* —— Shelf board: a flex container that fills its vertical track and
      centers the grid horizontally AND vertically so the shelf never
      needs to scroll out of view. */
#genre-board.scrapbook-board {
  display: flex;
  flex: 1 1 auto;
  align-items: center;
  justify-content: center;
  width: 100%;
  max-width: 100%;
  min-height: 0;
  padding: 0;
  margin: 0;
  background: transparent;
  box-shadow: none;
  position: relative;
}

#genre-board.scrapbook-board::before,
#genre-board.scrapbook-board::after {
  display: none;
}

/* The row is now a CSS grid of equally-sized cubbies. Each column
   stretches to fill available space, and new rows appear automatically
   when the cubbies run out of horizontal room. */
.scrapbook-row--shelf {
  display: grid;
  /* Locked to a 6-wide, 4-row rectangular shelving unit. With both
     axes at 1fr and `aspect-ratio: 6 / 4`, the grid scales down to
     fit whichever of the parent's width or height is more constraining,
     so the shelf always fits in the viewport without scrolling. */
  grid-template-columns: repeat(6, 1fr);
  grid-template-rows: repeat(4, 1fr);
  gap: 0;
  width: 100%;
  aspect-ratio: 6 / 4;
  /* The cap is derived only from the album + top plank + a hair of
     padding. The lip height is intentionally EXCLUDED so that making
     the genre-name panel taller covers more of the album instead of
     growing the cubby itself. */
  max-width: min(
    100%,
    calc((var(--shelf-album-size) + var(--shelf-top-height) + 0.6rem) * 6)
  );
  max-height: 100%;
  margin: 0 auto;
  position: relative;
  z-index: 3;
  /* Deep drop shadow below the whole shelving unit so it reads as one
     piece of furniture sitting in the room. No overflow clipping so
     hover lifts on cubbies aren't cropped at the edges. */
  filter: drop-shadow(0 18px 20px rgba(0, 0, 0, 0.55));
}

/* Legacy scrapbook row offset no longer applies. */
.scrapbook-row--bottom,
.scrapbook-row--top {
  margin-inline-start: 0;
}

/* —— Cubby (one per genre). Each is a complete framed box with its
      own top plank, side walls, honey-wood back, and angled front lip
      so the cubbies tile horizontally AND stack cleanly in rows. */
.scrapbook-row--shelf .genre-card {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  width: auto;
  min-width: 0;
  /* Every cubby fills its grid cell, which is already square because
     the outer grid has `aspect-ratio: 6 / 4` with equal-fraction tracks. */
  height: 100%;
  padding: calc(var(--shelf-top-height) + 0.4rem) var(--shelf-bin-pad-x) 0;
  margin: 0;
  /* The cubby's back wall is intentionally very dark so the album art
     pops forward like in a real record-store display. A hint of the
     wood texture still shows through to keep the material coherent
     with the lit wood on the frame, top plank, walls, and lip. */
  background:
    linear-gradient(180deg,
      rgba(0, 0, 0, 0.82) 0%,
      rgba(0, 0, 0, 0.92) 100%),
    var(--wood-texture);
  background-size: auto, 150% auto;
  background-position: center, center 35%;
  background-repeat: no-repeat, no-repeat;
  background-blend-mode: multiply, normal;
  transform: none;
  transition:
    transform 0.25s var(--ease-out),
    filter 0.25s var(--ease-out);
}

/* Top plank of each cubby — adjacent cubbies' planks tile into a
   continuous horizontal beam that reads as the shelf's top rail. */
.genre-bin-top {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: var(--shelf-top-height);
  background:
    linear-gradient(180deg,
      rgba(0, 0, 0, 0.52) 0%,
      rgba(0, 0, 0, 0.68) 100%),
    var(--wood-texture);
  background-size: auto, 300% auto;
  background-position: center, center 10%;
  background-repeat: no-repeat, no-repeat;
  background-blend-mode: multiply, normal;
  box-shadow:
    inset 0 1px 0 rgba(255, 240, 210, 0.22),
    inset 0 -1px 0 rgba(0, 0, 0, 0.5);
  z-index: 6;
  pointer-events: none;
}

/* Right wall of each cubby. Adjacent cubbies' walls touch to form the
   interior dividers; the last cubby's wall becomes the shelf's right
   edge. */
.scrapbook-row--shelf .genre-card::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  width: var(--shelf-wall-thickness);
  /* Side walls face perpendicular to the shelf's light, so they get a
     gentle edge-to-edge shade to read as a beveled plank. Grain still
     runs horizontally across the wall (matching the crate sides). */
  background:
    linear-gradient(90deg,
      rgba(0, 0, 0, 0.48) 0%,
      rgba(0, 0, 0, 0.7) 100%),
    var(--wood-texture);
  background-size: auto, auto 150%;
  background-position: center, right center;
  background-repeat: no-repeat, no-repeat;
  background-blend-mode: multiply, normal;
  box-shadow:
    inset 1px 0 0 rgba(255, 240, 210, 0.12),
    inset -1px 0 0 rgba(0, 0, 0, 0.45),
    -1px 0 4px rgba(0, 0, 0, 0.3);
  z-index: 5;
  pointer-events: none;
}

/* Left wall of each cubby. Its width matches the right wall so grid
   tracks are visually symmetric regardless of column index. */
.scrapbook-row--shelf .genre-card::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: var(--shelf-wall-thickness);
  background:
    linear-gradient(90deg,
      rgba(0, 0, 0, 0.7) 0%,
      rgba(0, 0, 0, 0.48) 100%),
    var(--wood-texture);
  background-size: auto, auto 150%;
  background-position: center, left center;
  background-repeat: no-repeat, no-repeat;
  background-blend-mode: multiply, normal;
  box-shadow:
    inset 1px 0 0 rgba(0, 0, 0, 0.45),
    inset -1px 0 0 rgba(255, 240, 210, 0.12),
    1px 0 4px rgba(0, 0, 0, 0.3);
  z-index: 5;
  pointer-events: none;
}

/* No hover lift or scale on shelf cards — the audio preview is the
   only hover response; the record stays put. Specificity here matches
   the legacy .genre-card:hover:not(:has(...)) rule so this wins. */
.scrapbook-row--shelf .genre-card:hover:not(:has(.stack-shuffle:hover)),
.scrapbook-row--shelf .genre-card:focus-within:not(:has(.stack-shuffle :focus)) {
  transform: none;
  z-index: auto;
}

/* Kill the polaroid frame around the album, and size the crate as a
   percentage of the cubby so the record scales with the grid instead
   of sticking to a fixed rem size. */
.scrapbook-row--shelf .genre-crate {
  position: relative;
  padding: 0;
  border: none;
  background: transparent;
  box-shadow: none;
  z-index: 2;
  width: 82%;
  aspect-ratio: 1 / 1;
  /* Push the record up off the bottom so the lip covers its lower edge. */
  margin-bottom: 14%;
  perspective: 900px;
  perspective-origin: 50% 40%;
}

/* The record sleeve — leans back like it's resting against the cubby. */
.scrapbook-row--shelf .card-inner {
  width: 100%;
  height: 100%;
  transform-origin: 50% 100%;
  transform: rotateX(var(--shelf-album-tilt));
  transform-style: preserve-3d;
  transition: transform 0.28s var(--ease-out);
}

.scrapbook-row--shelf .vinyl-wrap {
  width: 100%;
  height: 100%;
}

/* Neutralize every legacy hover transform/reveal for shelf cubbies —
   the record, album cover, vinyl peek, and backing squares all stay
   in their resting state. Only the audio preview (JS) still fires.
   Each selector mirrors the legacy :not(:has(...)) clause so we tie
   or beat the original rule's specificity. */
/* On hover/focus, straighten the album up (no lean) — paired with the
   audio preview. */
.scrapbook-row--shelf .genre-card:hover:not(:has(.stack-shuffle:hover)) .card-inner,
.scrapbook-row--shelf .genre-card:focus-within:not(:has(.stack-shuffle :focus)) .card-inner {
  transform: rotateX(0deg);
}

/* At rest, shelf albums keep the genre-color duotone tint (via the
   global `luminosity, normal` blend on `.card-inner::before/::after`
   and `.card-face`). On hover/focus we swap to `normal, normal` so
   the opaque artwork wins and the album shows in its original colors. */
.scrapbook-row--shelf .card-inner[data-has-board-cover="1"]::before,
.scrapbook-row--shelf .card-inner[data-has-board-cover="1"]::after,
.scrapbook-row--shelf .card-face[data-has-face-cover="1"] {
  transition: background-blend-mode 0.25s var(--ease-out);
}

.scrapbook-row--shelf .genre-card:hover:not(:has(.stack-shuffle:hover))
  .card-inner[data-has-board-cover="1"]::before,
.scrapbook-row--shelf .genre-card:hover:not(:has(.stack-shuffle:hover))
  .card-inner[data-has-board-cover="1"]::after,
.scrapbook-row--shelf .genre-card:hover:not(:has(.stack-shuffle:hover))
  .card-face[data-has-face-cover="1"],
.scrapbook-row--shelf .genre-card:focus-within:not(:has(.stack-shuffle :focus))
  .card-inner[data-has-board-cover="1"]::before,
.scrapbook-row--shelf .genre-card:focus-within:not(:has(.stack-shuffle :focus))
  .card-inner[data-has-board-cover="1"]::after,
.scrapbook-row--shelf .genre-card:focus-within:not(:has(.stack-shuffle :focus))
  .card-face[data-has-face-cover="1"] {
  background-blend-mode: normal, normal;
}

.scrapbook-row--shelf .genre-card:hover:not(:has(.stack-shuffle:hover)) .vinyl-wrap,
.scrapbook-row--shelf .genre-card:focus-within:not(:has(.stack-shuffle :focus)) .vinyl-wrap {
  opacity: 0;
  transform: scale(0.9);
  pointer-events: none;
}

.scrapbook-row--shelf .genre-card:hover:not(:has(.stack-shuffle:hover)) .card-face,
.scrapbook-row--shelf .genre-card:focus-within:not(:has(.stack-shuffle :focus)) .card-face {
  opacity: 1;
  transform: none;
}

.scrapbook-row--shelf .genre-card:hover:not(:has(.stack-shuffle:hover)) .card-inner::before,
.scrapbook-row--shelf .genre-card:hover:not(:has(.stack-shuffle:hover)) .card-inner::after,
.scrapbook-row--shelf .genre-card:focus-within:not(:has(.stack-shuffle :focus)) .card-inner::before,
.scrapbook-row--shelf .genre-card:focus-within:not(:has(.stack-shuffle :focus)) .card-inner::after {
  opacity: 1;
}

.scrapbook-row--shelf .genre-card:hover:not(:has(.stack-shuffle:hover)) .stack-shuffle,
.scrapbook-row--shelf .genre-card:focus-within:not(:has(.stack-shuffle :focus)) .stack-shuffle {
  opacity: 0;
  pointer-events: none;
}

/* "More records behind" — subtle neighbors offset to either side. */
.scrapbook-row--shelf .card-inner::before,
.scrapbook-row--shelf .card-inner::after {
  border: 1px solid rgba(0, 0, 0, 0.55);
  box-shadow:
    0 8px 14px rgba(0, 0, 0, 0.55),
    inset 0 0 0 1px rgba(255, 255, 255, 0.05);
  border-radius: 2px;
}

.scrapbook-row--shelf .card-inner[data-stack-arr="0"]::before,
.scrapbook-row--shelf .card-inner[data-stack-arr="1"]::before,
.scrapbook-row--shelf .card-inner[data-stack-arr="2"]::before,
.scrapbook-row--shelf .card-inner[data-stack-arr="3"]::before {
  transform: translate(-4px, 2px) rotate(1.5deg);
  opacity: 0.82;
}

.scrapbook-row--shelf .card-inner[data-stack-arr="0"]::after,
.scrapbook-row--shelf .card-inner[data-stack-arr="1"]::after,
.scrapbook-row--shelf .card-inner[data-stack-arr="2"]::after,
.scrapbook-row--shelf .card-inner[data-stack-arr="3"]::after {
  transform: translate(4px, 2px) rotate(-1.5deg);
  opacity: 0.88;
}

/* Front album cover: flat, crisp, square. */
.scrapbook-row--shelf .card-face {
  border-radius: 2px;
  border: 1px solid rgba(0, 0, 0, 0.55);
  box-shadow:
    0 10px 18px rgba(0, 0, 0, 0.55),
    inset 0 1px 0 rgba(255, 255, 255, 0.06);
}

/* —— Angled front lip — the sloped wooden panel across the bottom of
      each cubby that the records lean against. Injected via the
      .genre-bin-tag element (which becomes part of the lip). */
.genre-bin-tag {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  min-height: var(--shelf-lip-height);
  padding: 0 calc(var(--shelf-bin-pad-x) + 0.35rem);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.15rem;
  color: var(--label-ink);
  text-align: center;
  z-index: 4;
  pointer-events: none;
  background:
    linear-gradient(
      180deg,
      rgba(0, 0, 0, 0.46) 0%,
      rgba(0, 0, 0, 0.68) 100%
    ),
    var(--wood-texture);
  background-size: auto, 200% auto;
  background-position: center, center 70%;
  background-repeat: no-repeat, no-repeat;
  background-blend-mode: multiply, normal;
  /* Trapezoidal lip — narrower at top, wider at bottom, so it reads
     like a panel that angles out toward the viewer. */
  clip-path: polygon(
    0.75rem 0,
    calc(100% - 0.75rem) 0,
    100% 100%,
    0 100%
  );
  box-shadow:
    inset 0 1px 0 rgba(255, 240, 210, 0.28),
    inset 0 -2px 0 rgba(0, 0, 0, 0.45);
}

/* Dark edge/shadow cast by the lip onto the records above it. */
.genre-bin-tag::before {
  content: "";
  position: absolute;
  left: 0.75rem;
  right: 0.75rem;
  top: -0.35rem;
  height: 0.6rem;
  background: linear-gradient(180deg, rgba(0, 0, 0, 0.55) 0%, rgba(0, 0, 0, 0) 100%);
  border-radius: 2px 2px 0 0;
  pointer-events: none;
}

.genre-bin-tag-num {
  font-family: var(--font-sf-pro-display, var(--font-roboto));
  font-size: 0.58rem;
  font-weight: 700;
  letter-spacing: 0.22em;
  color: rgba(250, 230, 195, 0.55);
  text-transform: uppercase;
}

.genre-bin-tag-name {
  font-family: var(--font-sf-pro-display, var(--font-roboto));
  font-size: clamp(0.78rem, 1.4vmin, 0.88rem);
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  line-height: 1.05;
  color: rgba(250, 230, 195, 0.95);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.55);
}

/* Hide the old genre-name/rank baked into the card-face — the lip label
   is now the source of truth. Keep the face as a pure album cover. */
.scrapbook-row--shelf .card-face .genre-rank,
.scrapbook-row--shelf .card-face .genre-name {
  display: none;
}

/* Shuffle arrows are hidden on the shelf layout — hovering a cubby
   only plays the audio preview. The shuffle controls remain in the
   DOM so keyboard/JS access isn't broken. */
.scrapbook-row--shelf .genre-card-controls {
  display: none;
}

.scrapbook-row--shelf .stack-shuffle {
  transform: none;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.55));
  justify-content: space-between;
  padding: 0;
  gap: 0;
  width: 100%;
}

.scrapbook-row--shelf .stack-shuffle-btn {
  width: 1.45rem;
  height: 1.2rem;
  min-width: 1.45rem;
  border-radius: 0.3rem;
}


/* Responsive: on mobile the shelf reflows into a tall 2-column × 12-row
   layout so each album is large enough to tap. The page gains vertical
   scrolling because 12 rows are taller than the viewport. Breakpoint
   is generous (900px) so portrait tablets reflow too. */
@media (max-width: 900px) {
  :root {
    --shelf-album-size: clamp(7rem, 38vw, 13rem);
    --shelf-lip-height: 3.25rem;
    --shelf-top-height: 0.5rem;
    --shelf-base-height: 0.6rem;
    --shelf-wall-thickness: 0.45rem;
  }

  .scrapbook-row--shelf {
    grid-template-columns: repeat(2, 1fr) !important;
    grid-template-rows: repeat(12, 1fr) !important;
    aspect-ratio: 2 / 12 !important;
    max-width: min(
      100%,
      calc((var(--shelf-album-size) + var(--shelf-top-height) + 0.6rem) * 2)
    ) !important;
    max-height: none !important;
    margin-left: auto !important;
    margin-right: auto !important;
  }

  /* Break the desktop "lock to viewport" flex chain so content drives
     height and the document scrolls naturally on phones/tablets.
     IMPORTANT: only ONE element should be the scroll container — the
     <html> element. body / .page must be `overflow: visible` and
     content-driven height so they don't trap the shelf inside their
     own scroll context (which made scrolling feel buggy / clipped).
     Horizontal overflow is suppressed at the html level so the
     document never scrolls sideways. */
  html:has(#genre-board) {
    overflow-x: hidden !important;
    overflow-y: auto !important;
    height: 100dvh !important;
    max-width: 100% !important;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-y: contain !important;
  }
  body:has(#genre-board) {
    overflow: visible !important;
    height: auto !important;
    min-height: 100dvh !important;
    max-height: none !important;
    max-width: 100% !important;
  }

  .page:has(#genre-board) {
    height: auto !important;
    min-height: 100dvh !important;
    max-height: none !important;
    overflow: visible !important;
  }
  .page-main {
    flex: 0 0 auto !important;
    min-height: auto !important;
    /* Use overflow: visible (instead of overflow-x: hidden) so the
       element doesn't become a scroll container. The horizontal axis
       is already locked by `body { overflow-x: hidden }`, so we don't
       need to clip here. Setting overflow-x to a non-visible value
       would force the y-axis into `auto`, trapping the shelf inside
       page-main and blocking the body's natural scroll. */
    overflow: visible !important;
    /* Reserve enough room below the shelf so when the user scrolls all
       the way down the bottom row sits a couple rems above the fixed
       footer (footer height + ~2rem visual gap). */
    padding-bottom: calc(var(--shell-footer-offset) + 0.75rem) !important;
  }
  .board-wrap {
    padding: 1.5rem 0 0 !important;
    flex: 0 0 auto !important;
    min-height: auto !important;
    overflow: visible !important;
  }
  .board-scroll {
    flex: 0 0 auto !important;
    min-height: auto !important;
    overflow: visible !important;
    padding: 1.5rem max(1rem, env(safe-area-inset-right)) 0 max(1rem, env(safe-area-inset-left)) !important;
  }
  #genre-board.scrapbook-board {
    flex: 0 0 auto !important;
    align-items: flex-start !important;
    justify-content: center !important;
    min-height: auto !important;
  }

  /* Lock the layered home-page backdrop to the viewport on mobile so
     the dark wood gradient covers every pixel from the header all
     the way down past the last shelf row to the footer (instead of
     only the .page-main box, which can leave a gap at the bottom of
     long shelves). Using position: fixed pins the backdrop to the
     viewport, so it stays full-bleed while the content scrolls. */
  .page:has(#genre-board) .main-back,
  .page:has(#genre-board) .main-book,
  .page:has(#genre-board) .main-fore {
    position: fixed !important;
    inset: 0 !important;
    width: 100vw !important;
    height: 100dvh !important;
  }
}

