/* ==========================================================================
   Tape stack
   ==========================================================================
   Real <a> elements. The whole selection sequence is progressive enhancement:
   without JS the link navigates and the work page loads clean.
   ========================================================================== */
.tapes {
  margin: 0;
  padding: 0;
  list-style: none;
}

.tape {
  position: absolute;
  inset-inline-start: 50%;
  inset-block-end: calc((var(--tape-base) + (var(--tape-last) - var(--tape-index)) * var(--tape-pitch)) * var(--us));
  z-index: calc(10 + var(--tape-index));
  inline-size: calc(var(--tape-w) * var(--us));
  block-size: calc(var(--tape-h) * var(--us));
  transform: translateX(calc(-50% + var(--tape-offset, 0px)));
}
.tape:nth-child(even) { --tape-offset: calc(-1 * var(--tape-shift) * var(--us)); }

.tape__link {
  display: block;
  position: relative;
  inline-size: 100%;
  block-size: 100%;
  /* Hit area is the rendered box only — 61px tall and 61px apart leaves no
     room for a sloppy hitbox. */
  transform: translate3d(0, 0, 0);
  transform-origin: 50% 100%;
}
.tape__link img {
  position: relative;
  z-index: 1;
  inline-size: 100%;
  block-size: 100%;
  object-fit: fill;
  pointer-events: none;
}

/* The tape carries its own state now — no sibling glow layer. At rest the
   image is dimmed to --tape-dim: the tape is an unlit object in a dark room.
   Hover and focus lighten it to full brightness — the signal reaching it.

   filter: brightness() on the <img> is a compositor change: the tape box
   already sits on its own layer (transform: translate3d on .tape__link), so
   the swap never touches layout or triggers a paint storm. Nothing here
   animates width/height/top/left.

   Dark at rest; the hover lightens the tape itself to full brightness.
   Exit is deliberately faster and flatter than the enter (springs rule 2):
   the darken back down runs on --motion-state-exit, the lighten on
   --motion-state-enter. The asymmetry is the point — a symmetric fade reads
   as sluggish on the way out. */
.tape__link img {
  filter: brightness(var(--tape-dim));
  transition: filter var(--motion-state-exit);
}

/* The tapes do not move on hover. They are a stack of objects resting on the
   television, and lifting one on approach made the stack feel like a list of
   buttons rather than like a shelf. What hover does instead is light the tape
   up — the signal reaching it — and swap the readout.

   Gated to real pointers: touch fires a false hover on tap. */
@media (hover: hover) and (pointer: fine) {
  .tape__link:hover img {
    filter: brightness(1);
    transition: filter var(--motion-state-enter);
  }
}

/* Focus is not hover: it must be visible on every input type. It lightens the
   tape the same way hover does, and also draws the outline below. */
.tape__link:focus-visible { outline: none; }
.tape__link:focus-visible img {
  filter: brightness(1);
  transition: filter var(--motion-state-enter);
}
.tape__link:focus-visible::after {
  content: '';
  position: absolute;
  z-index: 2;
  inset: calc(-4 * var(--us));
  border: 1px solid rgba(241, 237, 228, 0.55);
}

/* Press feedback — instant, one pose, no waiting for a curve. This is the one
   place a tape moves under the pointer, and it should: a press that produces
   no movement at all reads as a dead control. */
.tape__link:active { transform: scale(0.994); }

/* Held while a selection sequence owns the stack. */
.tape.is-selected { z-index: 1; }
.tape.is-selected .tape__link { transition: none; }

/* No tape-specific reduced-motion block: the state tokens
   (--motion-state-enter / --motion-state-exit) already collapse to 1ms linear
   under prefers-reduced-motion in css/motion.css, so the brightness swap
   becomes instant with nothing to override here. */
