/* ---------- What has been on: the shelf (tickets/T74-l-etagere.md) ----------
   A24's shelf of discs, pressed as picture discs. It lives in the MORE column
   like the wheel did, but over the whole window: the canvas behind, the credit
   block in the top-left corner under the column's bar, what the desk heard at
   the foot. The column's bar stays — its label and its cross are the nav. */
.more > .shelf { position: fixed; inset: 0; z-index: 0; width: auto; opacity: 0; transition: opacity 0.6s ease; }
.shelf[hidden] { display: none; }
.shelf.is-up { opacity: 1; }
.shelf:focus { outline: none; }
/* The page goes all the way under: the records stand on the paper, not on a
   blurred player. Only the value — the ease is more.css's single list. */
body.is-shelf .page { opacity: 0; }

.shelf__stage { position: absolute; inset: 0; width: 100%; height: 100%; display: block; touch-action: none; }
.shelf__stage.is-pointing { cursor: pointer; }
.shelf__stage.is-grab { cursor: grab; }
.shelf__stage.is-grabbing { cursor: grabbing; }

/* The loop drawn round the record under the pointer, redrawn ten times a
   second. UNDER the canvas, which is transparent: a nearer record hides the
   stroke where it passes behind it, as A24's, drawn in its scene, does. */
.shelf__scribble { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; overflow: visible; }
.shelf__scribble path { fill: none; stroke: var(--ink); stroke-linecap: round; stroke-linejoin: round; }

/* ---------- Index: in the column's bar, on its middle line ---------- */
.shelf__index-key {
  position: absolute; top: var(--pad-top); left: 50%; translate: -50% 0;
  display: inline-flex; align-items: center; gap: 4px; height: 24px;
  font-size: 14px; line-height: 16px; color: var(--ink);
}
.shelf__index-key::before { content: ""; position: absolute; inset: calc(var(--hit-y) * -1) calc(var(--hit-x) * -1); }
.shelf__index-key .icon { transition: rotate 0.3s var(--ease-soft); }
.shelf__index-key[aria-expanded="true"] .icon { rotate: 180deg; }
.shelf__index-count { display: none; font-variant-numeric: tabular-nums; }
.shelf__index-key[aria-expanded="true"] .shelf__index-word { display: none; }
.shelf__index-key[aria-expanded="true"] .shelf__index-count { display: inline; }
@media (hover: hover) {
  .shelf__index-key:hover .shelf__index-word { display: none; }
  .shelf__index-key:hover .shelf__index-count { display: inline; }
}
.shelf__index {
  position: absolute; top: calc(var(--pad-top) + 36px); left: 50%; translate: -50% 0; z-index: 2;
  width: min(440px, calc(100vw - 32px));
  padding: 8px 12px;
  border-radius: var(--radius);
  background: var(--bg);
  box-shadow: 0 0 0 1px var(--ink), 0 12px 32px rgba(0, 0, 0, 0.08);
  animation: shelf-drop 0.32s var(--ease-soft);
}
.shelf__index[hidden] { display: none; }
@keyframes shelf-drop { from { opacity: 0; transform: translateY(-6px) scale(0.98); } }
.shelf__index-list { list-style: none; margin: 0; padding: 0; }
.shelf__index-list li + li { border-top: 1px solid var(--ink); }
.shelf__line { position: relative; display: grid; grid-template-columns: 48px 1fr auto; align-items: baseline; gap: 12px; width: 100%; padding: 6px 0 5px; text-align: left; font-size: 12px; line-height: 16px; color: var(--ink); }
.shelf__line-at { display: inline-flex; align-items: center; gap: 4px; font-variant-numeric: tabular-nums; }
.shelf__line-at .led { display: none; }
.shelf__line.is-now .led { display: block; background: var(--primary); }
.shelf__line-title { font: italic 400 16px/16px var(--font-display); letter-spacing: -0.01em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.shelf__line-artist { max-width: 16ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: right; }
.shelf__line[aria-current="true"]::before { content: ""; position: absolute; left: -9px; top: 50%; width: 4px; height: 4px; margin-top: -2px; border-radius: 50%; background: var(--ink); }
@media (hover: hover) { .shelf__line:hover .shelf__line-title { color: var(--primary); } }

/* ---------- The sheet: the record at the front, read like a credit block ---------- */
.shelf__sheet {
  position: absolute; left: var(--margin); top: calc(var(--pad-top) + 56px);
  width: clamp(248px, 21vw, 320px);
  visibility: hidden;
}
.shelf__title {
  margin: 0 0 12px;
  font: italic 400 clamp(32px, 3.1vw, 48px) / 0.92 var(--font-display);
  letter-spacing: -0.03em;
  text-wrap: balance;
}
.shelf__rows { margin: 0; }
.shelf__row { position: relative; display: flex; align-items: baseline; justify-content: space-between; gap: 16px; padding: 4px 0 3px; font-size: 12px; line-height: 16px; }
.shelf__row dt { flex: none; font-size: 10px; text-transform: uppercase; }
.shelf__row dd { margin: 0; min-width: 0; display: flex; align-items: center; justify-content: flex-end; gap: 6px; text-align: right; }
.shelf__row dd .shelf__roll { min-width: 0; }
.shelf__row .led { display: none; }
.shelf__row--air.is-now .led { display: block; background: var(--primary); animation: shelf-live 2.4s ease-in-out infinite alternate; }
@keyframes shelf-live { to { opacity: 0.45; } }
/* The rules are drawn, not bordered: on arrival they run in from the left one
   after the other, the way A24's credit block writes itself. */
.shelf__row::before, .shelf__row:last-child::after {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 1px;
  background: var(--ink); transform-origin: 0 50%;
}
.shelf__row:last-child::after { top: auto; bottom: 0; }
.shelf__heart {
  --r: 8;
  margin-top: 12px; display: inline-flex; align-items: center; gap: 8px;
  height: 24px; padding: 0 12px 0 8px; border-radius: 999px;
  font-size: 12px; line-height: 16px; color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--ink);
  transition: background-color 0.2s ease, color 0.2s ease, scale 0.16s var(--ease-soft);
}
.shelf__heart:active { scale: 0.96; }
.shelf__heart .icon--on { display: none; }
.shelf__heart[aria-pressed="true"] { background: var(--ink); color: var(--bg); }
.shelf__heart[aria-pressed="true"] .icon--on { display: block; }
.shelf__heart[aria-pressed="true"] .icon--off { display: none; }

/* ---------- What the desk heard: the two "reviews" under the record ---------- */
.shelf__reading {
  position: absolute; left: 50%; bottom: var(--pad-bottom); translate: -50% 0;
  display: flex; align-items: flex-start; justify-content: center; gap: clamp(40px, 6vw, 96px);
  pointer-events: none;
  visibility: hidden;
}
.shelf__quote { margin: 0; width: 17ch; display: flex; flex-direction: column; align-items: center; gap: 4px; text-align: center; transition: opacity 0.3s ease; }
.shelf__quote.is-empty { opacity: 0; }
.shelf__who { font-size: 10px; line-height: 16px; text-transform: uppercase; }
.shelf__what { margin: 0; font: italic 400 24px/24px var(--font-display); letter-spacing: -0.01em; text-wrap: balance; }
.shelf__pips { display: flex; align-items: center; gap: 3px; height: 16px; }
.shelf__pips i { width: 5px; height: 5px; border-radius: 50%; background: var(--ink); }
/* A pip not earned is a count at zero — the one place --ink-muted is a state here. */
.shelf__pips i.is-off { background: var(--ink-muted); }

.shelf__hint {
  position: absolute; left: var(--margin); bottom: var(--pad-bottom); margin: 0;
  display: flex; align-items: center; gap: 4px;
  font-size: 10px; line-height: 16px; text-transform: uppercase;
  transition: opacity 0.6s ease;
}
.shelf__hint kbd { font: inherit; display: inline-grid; place-items: center; min-width: 16px; height: 16px; border-radius: var(--radius); box-shadow: inset 0 0 0 1px var(--ink); }
.shelf__hint.is-gone { opacity: 0; }
.shelf__empty { position: absolute; left: 50%; top: 50%; translate: -50% -50%; margin: 0; max-width: 44ch; text-align: center; }
.shelf__empty[hidden] { display: none; }
.shelf__sr { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* ---------- Arrival: the sheet writes itself as the record rises ---------- */
.shelf.is-read .shelf__sheet, .shelf.is-read .shelf__reading { visibility: visible; }
.shelf.is-read .shelf__row::before, .shelf.is-read .shelf__row:last-child::after { animation: shelf-rule 0.9s var(--ease-soft) both; animation-delay: calc(var(--r) * 45ms); }
.shelf.is-read .shelf__row dt, .shelf.is-read .shelf__heart, .shelf.is-read .shelf__who, .shelf.is-read .shelf__pips { animation: shelf-fade 0.6s var(--ease-soft) both; animation-delay: calc(var(--r, 4) * 45ms + 120ms); }
@keyframes shelf-rule { from { transform: scaleX(0); } }
@keyframes shelf-fade { from { opacity: 0; transform: translateY(6px); } }

/* ---------- Letters that roll: a word changes letter by letter ---------- */
.shelf__roll { display: inline-grid; vertical-align: bottom; max-width: 100%; }
.shelf__roll > .line { grid-area: 1 / 1; min-width: 0; }
.shelf .word { display: inline-block; white-space: nowrap; clip-path: inset(-0.1em -0.4em -0.24em -0.4em); }
.shelf .ch { display: inline-block; white-space: pre; }
.shelf .line.is-in .ch { animation: shelf-ch-in 0.62s var(--ease-soft) both; animation-delay: calc(var(--i) * 14ms); }
.shelf .line.is-out { pointer-events: none; }
.shelf .line.is-out .ch { animation: shelf-ch-out 0.36s cubic-bezier(0.65, 0, 0.35, 1) both; animation-delay: calc(var(--i) * 8ms); }
@keyframes shelf-ch-in { from { transform: translateY(115%); } }
@keyframes shelf-ch-out { to { transform: translateY(-115%); } }
/* A row's value is short and sits on a hairline: it fades up whole, it does not roll. */
.shelf__row .shelf__roll > .line { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.shelf__row .word { clip-path: none; }
.shelf__row .line.is-in { animation: shelf-fade 0.48s var(--ease-soft) both; }
.shelf__row .line.is-in .ch, .shelf__row .line.is-out .ch { animation: none; }
.shelf__row .line.is-out { animation: shelf-out 0.24s ease both; }
@keyframes shelf-out { to { opacity: 0; transform: translateY(-6px); } }

/* ---------- Phone ---------- */
@media (max-width: 700px) {
  .shelf__index-key { top: var(--pad-top); left: auto; right: calc(var(--margin) + 48px); translate: none; }
  .shelf__sheet { left: var(--margin); right: var(--margin); width: auto; top: calc(var(--pad-top) + 48px); }
  .shelf__title { font-size: 40px; line-height: 40px; }
  .shelf__row { padding: 3px 0 2px; }
  .shelf__row--more { display: none; }
  .shelf__row:nth-child(6)::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1px; background: var(--ink); transform-origin: 0 50%; }
  .shelf.is-read .shelf__row:nth-child(6)::after { animation: shelf-rule 0.9s var(--ease-soft) both; animation-delay: calc(var(--r) * 45ms); }
  .shelf__heart, .shelf__hint { display: none; }
  .shelf__reading { left: var(--margin); right: var(--margin); translate: none; gap: 24px; bottom: calc(var(--pad-bottom) + env(safe-area-inset-bottom)); }
  .shelf__quote { width: auto; flex: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .shelf, .shelf * { animation: none !important; transition: none !important; }
}
