/* ==========================================================================
   PULSE — WHAT'S ON.

   No event cards. No boxes, no rounded rectangles, no grid of tiles. The index
   is a list of names set large enough to be architecture, with an index number,
   a type and a mark — and the photograph is something the list BRINGS WITH IT
   rather than something each row contains.

   Two interactions, one state:

     desktop   pointer or keyboard focus on a row TUNES it in — the plate takes
               that event's photograph, the beat line takes its waveform, the
               section takes its colours and the other three rows drop back.
               Pressing it OPENS the row.
     phone     no hover to depend on. A tap opens the row in place, and any
               other open row closes. Same panel, same data, same aria.
   ========================================================================== */
.events {
  padding-block: var(--stack);
  background:
    radial-gradient(120% 80% at 78% 22%,
      color-mix(in srgb, var(--wash) 78%, transparent) 0%, transparent 62%);
  transition: background 700ms linear;
}

.events__headline { margin-bottom: clamp(1.2rem, 2.4vw, 2rem); }
.events .lead { margin-bottom: clamp(2.5rem, 6vw, 5rem); }

.events__field {
  position: relative;
  width: min(100% - var(--gut) * 2, var(--wrap));
  margin-inline: auto;
}

/* --- the plate -------------------------------------------------------------
   The photograph the tuned-in row brings with it. It is allowed to follow the
   pointer, but barely: --px and --py are clamped to a few dozen pixels by
   frequency.js, because an image that chases the cursor reads as a toy. */
.events__plate {
  position: absolute;
  top: 50%;
  /* clear of the type column on the right: the photograph is meant to sit
     BEHIND the event titles, not underneath the small mono metadata, which
     would be unreadable over a lit crowd shot */
  right: 13%;
  z-index: 0;
  translate: 0 -50%;
  transform: translate3d(var(--px, 0px), var(--py, 0px), 0);
  transition: transform 420ms cubic-bezier(0.22, 1, 0.32, 1);
  pointer-events: none;
  opacity: 0;
}
.events__plate.is-live { opacity: 1; }
.plate__img {
  position: absolute;
  inset: 0;
  opacity: 0;
  /* a CUT, not a fade-up: 120ms, no movement, no scale */
  transition: opacity var(--cut);
}
.plate__img.is-live { opacity: 1; }
.plate__img img { width: 100%; height: 100%; object-fit: cover; }

/* A hairline frame rather than a rounded card — and, in the same layer, the
   thing that makes the composition work: the photograph sits BEHIND the
   typography, so its left edge is sunk back into the page colour and the title
   crossing it stays a title rather than becoming texture. ::after paints above
   the images, so one inset shadow does it without a second element. */
.events__plate::after {
  content: '';
  position: absolute;
  inset: 0;
  border: 1px solid color-mix(in srgb, var(--glow) 55%, transparent);
  box-shadow:
    inset 120px 0 90px -50px var(--bg),
    inset -50px 0 60px -50px var(--bg);
  pointer-events: none;
}

@media (max-width: 999px) { .events__plate { display: none; } }

/* --- the rows --------------------------------------------------------------- */
.events__list { position: relative; z-index: 1; }

.ev { border-top: 1px solid var(--rule); }
.ev:last-child { border-bottom: 1px solid var(--rule); }

.ev__hit {
  display: grid;
  /* four children: index, title, type, mark. Three columns put the mark on a
     second row and left a stray arrow under every event. */
  grid-template-columns: auto minmax(0, 1fr) auto auto;
  align-items: baseline;
  gap: clamp(0.7rem, 2vw, 1.6rem);
  width: 100%;
  min-height: 64px;
  padding: clamp(0.9rem, 2vw, 1.6rem) 0;
  text-align: left;
  cursor: pointer;
  transition: opacity var(--snap);
}

.ev__no {
  color: var(--glow);
  transition: color var(--cut);
}

.ev__title {
  font-family: var(--display);
  /* the title occupies most of the viewport width, which is the brief's actual
     requirement — so it is sized from the viewport, not from a type scale */
  font-size: clamp(1.9rem, 7.4vw, 6.4rem);
  line-height: 0.9;
  letter-spacing: -0.03em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--ink) 76%, transparent);
  transition: color var(--cut);
}

.ev__type {
  font-family: var(--mono);
  font-size: var(--t-mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-faint);
  white-space: nowrap;
  transition: color var(--cut);
}

.ev__mark {
  font-size: 1.2rem;
  color: var(--ink-faint);
  transition: transform var(--snap), color var(--cut);
}

/* tuned in: brighter title, the mark moves, the number takes the frequency */
.ev.is-tuned .ev__title { color: var(--ink); }
.ev.is-tuned .ev__type  { color: var(--glow); }
.ev.is-tuned .ev__mark  { color: var(--glow); transform: translateX(6px); }

/* the other rows step back — reduced contrast, never hidden */
.events__list.has-tuned .ev:not(.is-tuned) .ev__hit { opacity: 0.42; }

/* open: the row is a state, and it is not signalled by colour alone. The rule
   on the left is the shape that says "this one", for anyone who cannot separate
   the tuned title from the untuned ones. */
.ev.is-open { border-left: 3px solid var(--glow); }
.ev.is-open .ev__hit { padding-left: clamp(0.7rem, 1.6vw, 1.2rem); opacity: 1; }
.ev.is-open .ev__title { color: var(--ink); }
.ev.is-open .ev__mark { transform: rotate(90deg); }

/* --- the panel -------------------------------------------------------------- */
.ev__panel {
  display: grid;
  grid-template-columns: minmax(0, 480px) minmax(0, 1fr);
  gap: clamp(1.2rem, 3vw, 2.6rem);
  padding: 0 0 clamp(1.6rem, 3vw, 2.6rem);
}
.ev__panel[hidden] { display: none; }

.ev__text { display: flex; flex-direction: column; align-items: flex-start; gap: 1rem; }
.ev__desc { font-size: var(--t-lead); line-height: 1.5; max-width: 44ch; color: var(--ink); }
.ev__music { color: var(--glow); }

@media (max-width: 899px) {
  /* on a phone the type moves under the title rather than beside it, so the
     title keeps the full width it is supposed to have */
  .ev__hit {
    grid-template-columns: auto minmax(0, 1fr) auto;
    row-gap: 0.35rem;
  }
  .ev__type { grid-column: 2 / 4; grid-row: 2; white-space: normal; }
  .ev__panel { grid-template-columns: 1fr; }
  .ev__fig { width: 100%; }
}

/* --- the section's own beat line -------------------------------------------- */
.events .beat--wide {
  margin-top: clamp(2rem, 5vw, 3.5rem);
}
