/* ============================================================================
   6 · ALUMNI — band-brand: the affiliations, and the deck of recordings.
   A full-width insert with rounded corners. In live mode it waits as a
   small violet bar across the conduit's four lines, then opens from the
   first line, sides and bottom edge together (an inline clip-path from
   conduit.js, removed once it is fully open).

   Flagged for review, not yet decided: against §8.1 "transform and opacity
   only", the deck's opened card turns 16:9 by a width, height and top
   transition, as a scale would stretch the recording. One absolutely
   placed element, so nothing around it reflows.
   ========================================================================= */

.alumni {
  /* tier-3, scoped */
  --points-trace: var(--purple-300);  /* the sparkle round an affiliation (sparkle.css) */
  --aff-edge: var(--purple-300);      /* 3.7:1 on purple-700: clears the 3:1 boundary floor */
  --deck-nav: 44px;                   /* the arrow buttons, §10.1 button-icon */
  padding: var(--space-section) 0;
  border-radius: var(--radius-lg);
  overflow-x: clip;                   /* the deck's outer cards, on a phone */
}

.alumni__layout {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  grid-template-areas:
    "head player"
    "affs player";
  grid-template-rows: auto 1fr;
  column-gap: var(--space-12);
}
.alumni__head   { grid-area: head; }
.alumni__affs   { grid-area: affs; }
.alumni__player { grid-area: player; }

.alumni__title { max-width: 16ch; }
.alumni__lead {
  margin: var(--space-6) 0 0;
  max-width: 48ch;
  font-size: var(--type-lead);
  line-height: 1.65;
  color: var(--color-body);
}

/* --- the affiliations: an invisible three-column grid ------------------
   Each name on two lines, centred in its cell. alumni.js sets --aff-size by
   area, clamped between {type.body} and {type.h2}: long names set smaller,
   short ones larger, and the nine read as the same size. No borders, no
   fills. The columns take their names' width and the grid sits left, pulled
   out by the cell and name padding so the first column's text starts on the
   heading's left edge. */
.alumni__affs {
  display: grid;
  grid-template-columns: repeat(3, auto);
  justify-content: start;
  align-content: start;
  gap: var(--space-2) var(--space-4);
  margin: var(--space-6) 0 0 calc(var(--space-2) * -2);
  padding: 0; list-style: none;
}
.alumni__affs li { display: flex; min-width: 0; }
/* The alumni map link: the grid's last row, across every column, so it
   centres under the names whatever width the columns take. */
.alumni__affs .alumni__map {
  grid-column: 1 / -1;
  justify-self: center;
  margin-top: var(--space-6);
}

/* The affiliation button, all five states, answering as the section-3 and
   section-4 labels do: hover and focus grow the name 3% and run the
   sparkle round it (sparkle.css, .points__trace); a click runs it again
   (.is-sparked, alumni.js); picked, the name grows 8% and takes ink;
   disabled, it dims. The name scales in place, so nothing moves. */
.aff {
  flex: 1;
  min-width: 0;
  display: grid;
  place-items: center;
  min-height: 44px;
  padding: var(--space-3) var(--space-2);
  box-sizing: border-box;
  border: 0;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--color-body);
  text-align: center;
  cursor: pointer;
  transition: color var(--motion-fast);
}
.aff__name {
  position: relative;
  display: inline-block;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  font: 500 var(--aff-size, var(--type-h4)) / 1.15 var(--font-body);
  transition: scale var(--motion-medium);
}
.aff__line { display: block; width: max-content; margin: 0 auto; white-space: nowrap; }   /* max-content: alumni.js measures it */
.aff:hover { color: var(--color-ink); }
.aff:is(:hover, :focus-visible) .aff__name { scale: 1.03; }
.aff:focus-visible { outline: 3px solid var(--color-focus-ring); outline-offset: 2px; }
.aff:active { color: var(--color-ink); }
.aff[aria-pressed="true"] { color: var(--color-ink); }
.aff[aria-pressed="true"] .aff__name { scale: 1.08; }
.aff:disabled { opacity: 0.5; cursor: not-allowed; }
.aff:disabled .aff__name { scale: none; }
.aff.is-sparked .points__trace,
.aff:hover .points__trace { animation: points-spark 1.8s cubic-bezier(0.45, 0.05, 0.55, 0.95); }

/* --- the deck: clear glass panes, one recording each --------------------
   The centre pane (data-pos 0) faces the reader. The others stand in two
   stacks, one each side, set well apart from it, turned towards it and
   packed close, like a stack of Aero windows. The panes are clear: the
   band shows through, frosted, and overlapping panes read as layered
   glass. The deck has ends: each turn moves one pane from one stack into
   the centre and the old centre onto the other stack, until a side runs
   out. Each stack keeps the same footprint however many panes it holds:
   alumni.js sets --a (the place, counted out from the centre), --side (-1
   left, 1 right) and --t (0 for a stack's first pane to 1 for its last),
   and a fuller stack packs its panes closer. alumni.js turns the deck one
   place at a time, so a long move reads as the stack turning. Opened
   (.is-open on the player), the centre pane widens and the stacks fade
   out. */
.deck {
  container-type: inline-size;
  display: grid;
  grid-template-columns: var(--deck-nav) minmax(0, 1fr) var(--deck-nav);
  grid-template-areas: "prev stage next";
  align-items: center;
  column-gap: var(--space-4);
}
.deck__nav--prev { grid-area: prev; }
.deck__stage     { grid-area: stage; }
.deck__nav--next { grid-area: next; }

.deck__stage {
  /* tier-3, scoped: the card's width, and how far each place sits from the
     centre. cqw is the deck's width. */
  /* the width fits the centre pane and both stacks (2.64 panes) between the arrows */
  --stage-w: calc(100cqw - (var(--deck-nav) + var(--space-4)) * 2);
  --card-w: min(240px, calc(var(--stage-w) / 2.64));
  /* Opened, the pane takes the recordings' 16:9 and runs out to the arrows,
     no taller than the stage: 256/81 is the 9:16 pane's height at 16:9. */
  --open-w: min(var(--stage-w), calc(var(--card-w) * 256 / 81));
  --near: calc(var(--card-w) * 0.78);   /* the first pane of a stack, from the centre */
  --span: calc(var(--card-w) * 0.36);   /* a stack's first pane to its last */
  position: relative;
  perspective: 1200px;
  height: calc(var(--card-w) * 16 / 9);
  touch-action: pan-y;   /* a sideways swipe turns the deck (alumni.js), not the page */
}

.deck__card {
  --a: 0;
  --side: 0;
  --t: 0;
  --x: calc(var(--side) * (var(--near) + var(--span) * var(--t)));
  --s: calc(0.74 - 0.12 * var(--t));
  --turn: calc(var(--side) * -55deg);
  position: absolute;
  top: 0; left: 50%;
  width: var(--card-w);
  height: 100%;
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  border: 1px solid var(--color-hairline-on-band);
  border-radius: var(--radius-lg);
  /* clear glass: a sheen across the top corner, nothing solid behind it */
  background: linear-gradient(155deg, var(--color-wash-on-band-strong) 0%, var(--color-hairline-on-band-soft) 30%, transparent 55%);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  z-index: calc(20 - var(--a));
  transform: translateX(calc(-50% + var(--x))) rotateY(var(--turn)) scale(var(--s));
  transition: transform var(--motion-slow), width var(--motion-slow),
              height var(--motion-slow), top var(--motion-slow),
              opacity var(--motion-slow), border-color var(--motion-fast);
}
/* the sheen over the recording, so the pane still reads as glass */
.deck__card::after {
  content: "";
  position: absolute; inset: 0;
  border-radius: inherit;
  background: linear-gradient(155deg, var(--color-wash-on-band-strong) 0%, transparent 35%);
  pointer-events: none;
}
.deck__card[data-pos="0"] { --x: 0px; --s: 1; --turn: 0deg; }
.alumni__player.is-open .deck__card[data-pos="0"] {
  width: var(--open-w);
  height: calc(var(--open-w) * 9 / 16);
  top: calc((100% - var(--open-w) * 9 / 16) / 2);   /* centred in the stage's height */
}
.alumni__player.is-open .deck__card:not([data-pos="0"]) { opacity: 0; pointer-events: none; }

.deck__screen,
.deck__video {
  display: grid;   /* the placeholder's label centred; the video fills it */
  width: 100%;
  height: 100%;
  object-fit: cover;
  border: 0;   /* the YouTube player's frame */
  border-radius: inherit;
  overflow: hidden;
  background: none;
  transition: opacity var(--motion-slow);
}
.deck__screen.ph { background: none; }   /* the placeholder stays clear too */
/* The recording is see-through, so the pane keeps its glass: more so at
   rest and in the stacks, least while it plays. */
.deck__video { opacity: 0.72; }
.deck__card:not([data-pos="0"]) .deck__video { opacity: 0.4; }
.alumni__player.is-open .deck__card[data-pos="0"] .deck__video { opacity: 0.9; }
/* A placeholder's label only on the centre card: cut off at the sides. */
.deck__screen.ph::after { transition: opacity var(--motion-medium); }
.deck__card:not([data-pos="0"]) .ph::after { opacity: 0; }

/* The whole card is the button: the centre card opens and closes, a side
   card comes to the centre. While an opened card has a recording, alumni.js
   hides it, so the video's own controls take the clicks. */
.deck__hit {
  position: absolute; inset: 0;
  padding: 0;
  border: 0;
  border-radius: inherit;
  background: transparent;
  cursor: pointer;
  display: grid;
  place-items: center;
}
.deck__hit[hidden] { display: none; }   /* display: grid would otherwise override it */
.deck__hit:focus-visible { outline: 3px solid var(--color-focus-ring); outline-offset: 2px; }
.deck__hit:disabled { cursor: not-allowed; }
.deck__card:has(.deck__hit:hover),
.deck__card:has(.deck__hit:focus-visible) { border-color: var(--aff-edge); }
.deck__card[data-pos="0"]:has(.deck__hit:active) { --s: 0.98; }

/* The play mark on the centre pane: a disc of the same frosted glass, its
   tint a little deeper so the white triangle holds over a light frame.
   Hidden on the stacks and once the pane is open (the video's own
   controls take over). It follows the whole pane's states: hover and focus
   grow it and brighten its rim, a press sinks it, disabled dims it. */
.deck__play {
  display: grid;
  place-items: center;
  width: var(--space-16);
  height: var(--space-16);
  border: 1px solid var(--color-hairline-on-band);
  border-radius: var(--radius-full);
  background: linear-gradient(155deg, var(--color-wash-on-band-strong) 0%, transparent 60%),
              color-mix(in srgb, var(--purple-900) 30%, transparent);
  -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
  color: var(--color-ink);
  opacity: 0;
  transform: scale(0.8);
  transition: opacity var(--motion-medium), transform var(--motion-medium), border-color var(--motion-fast);
}
.deck__play svg { width: var(--space-6); height: var(--space-6); margin-left: 3px; fill: currentColor; }   /* 3px: the triangle's optical centre */
.deck__card[data-pos="0"] .deck__play { opacity: 1; transform: none; }
.deck__card[data-pos="0"] .deck__hit:is(:hover, :focus-visible) .deck__play { transform: scale(1.08); border-color: var(--aff-edge); }
.deck__card[data-pos="0"] .deck__hit:active .deck__play { transform: scale(0.94); }
.deck__hit:disabled .deck__play { opacity: 0.5; }
.alumni__player.is-open .deck__card[data-pos="0"] .deck__play { opacity: 0; transform: scale(0.8); }
/* A missing recording's label drops to the foot of the pane, clear of the play mark. */
.deck__screen.ph { place-items: end center; padding-bottom: var(--space-8); }

/* The arrows, beyond the stack either side: §10.1 button-icon, all five
   states. The ring takes --aff-edge, as a hairline would fail 3:1 here. */
.deck__nav {
  position: relative; z-index: 5;
  display: grid; place-items: center;
  width: var(--deck-nav); height: var(--deck-nav);
  padding: 0;
  border: 1px solid var(--aff-edge);
  border-radius: var(--radius-full);
  background: transparent;
  color: var(--color-ink);
  cursor: pointer;
  transition: background-color var(--motion-fast), border-color var(--motion-fast), transform var(--motion-fast);
}
.deck__nav svg { fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.deck__nav:hover { border-color: var(--color-ink); background: var(--color-canvas-tinted); }
.deck__nav:focus-visible { outline: 3px solid var(--color-focus-ring); outline-offset: 2px; }
.deck__nav:active { background: var(--color-canvas-pressed); transform: scale(0.94); }
.deck__nav:disabled { opacity: 0.5; transform: none; cursor: not-allowed; }

/* --- the caption under the deck: centred under the stage --------------- */
.who {
  display: grid;
  margin-top: var(--space-6);
  padding: 0 calc(var(--deck-nav) + var(--space-4));
  text-align: center;
}
.who__item {
  grid-area: 1 / 1;
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--motion-medium), visibility 0s var(--motion-medium);
}
.who__item.is-on { opacity: 1; visibility: visible; transition: opacity var(--motion-medium); }
.who__name {
  margin: 0;
  font-size: var(--type-h3);
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -0.01em;
  color: var(--color-ink);
}
.who__based {
  margin: var(--space-1) 0 0;
  font-size: var(--type-body-sm);
  line-height: 1.5;
  color: var(--color-muted);
}
.who__org {
  margin: var(--space-4) 0 0;
  font-size: var(--type-label);
  font-weight: 600;
  line-height: 1.4;
  color: var(--color-ink);
}
.who__quote { margin: var(--space-3) 0 0; }
.who__quote p {
  margin: 0 auto;
  max-width: 52ch;
  font-size: var(--type-body);
  line-height: 1.6;
  color: var(--color-body);
}
.who__quote p::before { content: "\201C"; }
.who__quote p::after  { content: "\201D"; }

/* ---- responsive (§13.1) — review at 1440, 1180, 980, 720, 480, 390 ------ */

/* Where the band has the margin, the alumni deck runs into it, so the
   centre pane keeps its size beside two stacks of four. */
@media (min-width: 1320px) {
  .alumni__player { margin-right: calc(var(--space-16) * -1); }
}

/* Below 980px the affiliations stay under their heading, the deck under them. */

@media (max-width: 979px) {
  .alumni__layout {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "head" "affs" "player";
    grid-template-rows: auto;
  }
  .alumni__player { margin-top: var(--space-12); max-width: 640px; }
}

@media (max-width: 719px) {
  /* The arrows drop under the stack, so the cards take the full width. */
  .deck {
    grid-template-columns: 1fr 1fr;
    grid-template-areas: "stage stage" "prev next";
    row-gap: var(--space-6);
  }
  .deck__stage { --stage-w: 100cqw; --card-w: min(240px, 56cqw); }   /* the stacks run off the band's edge */
  /* The affiliation buttons go, and the lead that introduces them: the
     panes swipe (alumni.js) and the arrows turn them. The alumni map link
     stays. */
  .alumni__lead,
  .alumni__affs li:not(.alumni__map) { display: none; }
  .alumni__affs { grid-template-columns: minmax(0, 1fr); margin-left: 0; }
  .deck__nav--prev { justify-self: end; }
  .deck__nav--next { justify-self: start; }
  .who { padding: 0; }
}
