/*
 * Party explainer prototype (/parties/greens/, issue #134).
 *
 * A scroll-driven explainer: a sticky diagram (public/js/partyLab.js draws it
 * as one SVG) and a column of short steps that pass beside it on a wide
 * screen and over its lower edge on a phone. site.css, content.css and
 * research.css supply the tokens and the article furniture; only the scrolly
 * layout and the diagram's own marks live here.
 *
 * Every mark's motion is a CSS transition on opacity or transform, so the
 * global prefers-reduced-motion rule in site.css turns all of it off and each
 * step simply shows its final state. partyLab.js checks the same query for
 * the one sequence it drives itself (the chain) and for the staggered
 * entrance delays.
 */

.lab-page {
  max-width: 1120px;
}

.lab-page .article-header,
.lab-page > .caveat,
.lab-after,
.lab-page .research-footer {
  max-width: 820px;
}

/* ------------------------------------------------------------ the scrolly */

.lab-scrolly {
  position: relative;
  margin: 32px 0 48px;
}

.lab-scrolly:not(.is-ready) .lab-figure-wrap {
  /* No diagram without JavaScript or the live compass: the steps alone. */
  display: none;
}

.lab-figure-wrap {
  position: sticky;
  top: var(--nav-height);
  z-index: 1;
  background-color: var(--base);
  padding: 8px 0;
}

.lab-figure {
  margin: 0 auto;
  background-color: var(--raised);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 10px;
  max-width: 560px;
}

.lab-svg {
  display: block;
  width: 100%;
  height: auto;
  /* On a short or narrow screen the diagram must leave room for the step text
     that scrolls under it, so its height, not its width, is what gives. */
  max-height: calc(56vh - 40px);
  margin: 0 auto;
}

.lab-caption {
  color: var(--muted);
  font-size: 0.85rem;
  line-height: 1.5;
  margin: 8px 4px 0;
}

.lab-stepnav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-top: 8px;
}

.lab-stepnav[hidden] {
  display: none;
}

.lab-stepnav-btn {
  font: inherit;
  font-size: 0.8rem;
  color: var(--text);
  background-color: var(--plot);
  border: 1px solid var(--edge);
  border-radius: var(--radius-pill);
  padding: 6px 12px;
  min-height: 34px;
  cursor: pointer;
}

.lab-stepnav-btn:hover,
.lab-stepnav-btn:focus-visible {
  background-color: var(--edge);
}

.lab-stepnav-btn:disabled {
  opacity: 0.45;
  cursor: default;
}

.lab-stepnav-count {
  font-size: 12px;
  color: var(--muted);
}

.lab-steps {
  list-style: none;
  margin: 0;
  padding: 0;
  position: relative;
  z-index: 2;
}

.lab-step {
  /* Tall enough that only one step is near the trigger line at a time. */
  min-height: 78vh;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: 0 0 18vh;
  /* Children keep the card look; the step box itself is invisible, so the
     diagram stays visible between cards. */
  pointer-events: none;
}

.lab-step > * {
  pointer-events: auto;
}

.lab-step:first-child {
  min-height: 60vh;
}

.lab-step:last-child {
  padding-bottom: 8vh;
}

.lab-step-num,
.lab-step h2,
.lab-step p,
.lab-step .lab-list {
  background-color: var(--raised);
  margin: 0;
  padding: 0 18px;
  border-left: 1px solid var(--line);
  border-right: 1px solid var(--line);
}

.lab-step .lab-step-num {
  /* Scoped as .lab-step .lab-step-num so it outranks the ".lab-step p" card
     rule above, which used to zero this top padding and turn the label grey. */
  border-top: 1px solid var(--line);
  border-radius: var(--radius) var(--radius) 0 0;
  padding-top: 16px;
  font-size: 12px;
  color: var(--bone);
  letter-spacing: 0.06em;
}

.lab-step h2 {
  color: var(--text);
  font-size: 1.25rem;
  line-height: 1.3;
  padding-top: 6px;
  padding-bottom: 8px;
  outline: none;
}

.lab-step h2:focus-visible {
  text-decoration: underline;
  text-decoration-color: var(--bone);
  text-underline-offset: 4px;
}

.lab-step p,
.lab-step .lab-list {
  color: var(--muted);
  line-height: 1.6;
  padding-bottom: 10px;
}

.lab-step .lab-list {
  padding-left: 40px;
}

.lab-step .lab-list li + li {
  margin-top: 4px;
}

.lab-step > :last-child {
  border-bottom: 1px solid var(--line);
  border-radius: 0 0 var(--radius) var(--radius);
  padding-bottom: 18px;
}

.lab-step.is-active .lab-step-num,
.lab-step.is-active h2,
.lab-step.is-active p,
.lab-step.is-active .lab-list {
  border-color: var(--edge);
}

.lab-step .lab-step-note {
  font-size: 0.875rem;
  line-height: 1.55;
}

.lab-step .cta-button {
  margin: 4px 0 0;
}

/* Words that name a mark in the diagram take that mark's colour. The party
   colour arrives from /api/survey: partyLab.js sets --lab-party on the page
   (lightened if it would read poorly on the card), and until then, or
   without JavaScript, the words are plain text colour. */
.lab-ink-party,
.lab-ink-bone,
.lab-ink-muted {
  font-weight: 600;
}

.lab-ink-party {
  color: var(--lab-party, var(--text));
}

.lab-ink-bone {
  color: var(--bone);
}

.lab-ink-muted {
  color: var(--muted);
}

/* Wide screens: steps in a column on the left, the diagram sticky beside them. */
@media (min-width: 900px) {
  .lab-scrolly {
    display: grid;
    grid-template-columns: minmax(300px, 380px) minmax(0, 1fr);
    gap: 40px;
    align-items: start;
  }

  /* The wrap fills the screen below the nav and centres the figure in it,
     so the diagram sits in the middle of the view, level with the step
     beside it, instead of pinned to the top. */
  .lab-figure-wrap {
    grid-column: 2;
    grid-row: 1;
    top: var(--nav-height);
    height: calc(100vh - var(--nav-height));
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 0;
    background-color: transparent;
  }

  .lab-figure {
    width: 100%;
  }

  .lab-steps {
    grid-column: 1;
    grid-row: 1;
  }

  .lab-svg {
    max-height: calc(100vh - var(--nav-height) - 100px);
  }

  .lab-step {
    justify-content: center;
    min-height: 92vh;
    padding: 0;
  }

  .lab-step:first-child {
    min-height: 70vh;
  }

  /* Side by side, two or three cards can be on screen at once. The one the
     diagram is showing stays at full strength and the others step back, so
     the eye pairs the right card with the picture. Only once the diagram is
     running: without it there is no active step to pair with. */
  .lab-scrolly.is-ready .lab-step > * {
    transition: opacity var(--lab-in) ease;
  }

  .lab-scrolly.is-ready .lab-step:not(.is-active) > * {
    opacity: 0.6;
  }
}

/* The caption is the diagram's text alternative (the SVG is labelled by it).
   It repeats what the step text beside it already says, so it is kept for
   screen readers only and the diagram keeps the height. */
.lab-caption {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* Phones: the diagram stays pinned under the nav and the steps scroll up
   behind it, so a card never covers the picture it describes. The gap
   between cards keeps one step at a time in the reading area below. */
@media (max-width: 899px) {
  .lab-figure-wrap {
    z-index: 3;
  }

  .lab-steps {
    z-index: 1;
  }

  .lab-step {
    min-height: 0;
    justify-content: flex-start;
    padding: 0 0 42vh;
  }

  .lab-step:first-child {
    min-height: 0;
    padding-top: 4vh;
  }

  .lab-figure {
    padding: 6px;
  }

  .lab-stepnav {
    margin-top: 4px;
  }
}

/* ---------------------------------------------------------- diagram marks */

.lab-svg text {
  font-family: 'Inter', system-ui, sans-serif;
}

.lab-svg .lab-mono {
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
}

/* One timing system for every mark. Things that leave go quickly and first;
   things that arrive wait for them, then take a little longer, so two
   layers are never on screen at half strength together (a cross-fade reads
   as mud, a hand-over reads as a cut). Geometry that changes (bars, dots,
   the camera) uses one ease-out curve, so every move in the piece settles
   the same way. partyLab.js reads --lab-out for its own delays. */
.lab-page {
  --lab-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --lab-out: 0.28s;
  --lab-in: 0.55s;
  --lab-move: 0.85s;
}

.lab-layer {
  transition: opacity var(--lab-in) ease var(--lab-out), visibility 0s linear 0s;
}

.lab-fade {
  transition: opacity var(--lab-in) ease;
}

.lab-layer.is-off {
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--lab-out) ease, visibility 0s linear var(--lab-out);
}

.lab-grow {
  transition: transform var(--lab-move) var(--lab-ease), opacity var(--lab-in) ease;
}

.lab-move {
  transition: transform var(--lab-move) var(--lab-ease), opacity var(--lab-in) ease;
}

/* The compass camera (the chain step zooms in on the chain). */
.lab-camera {
  transition: transform var(--lab-move) var(--lab-ease);
}

/* The party dot lands at the end of the chain: one ring, once. */
.lab-pulse {
  fill: none;
  opacity: 0;
  transform-box: fill-box;
  transform-origin: center;
}

.lab-pulse.is-on {
  animation: lab-pulse 0.9s var(--lab-ease) 1;
}

@keyframes lab-pulse {
  from {
    opacity: 0.9;
    transform: scale(1);
  }

  to {
    opacity: 0;
    transform: scale(2.6);
  }
}

/* ------------------------------------------------------------- after part */

.lab-after h2 {
  color: var(--text);
  font-size: clamp(1.3rem, 3.5vw, 1.6rem);
  margin-top: 40px;
}

.lab-after p {
  color: var(--muted);
  line-height: 1.7;
  max-width: 68ch;
}

.lab-details {
  background-color: var(--raised);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 14px 18px;
  margin: 18px 0;
}

.lab-details summary {
  cursor: pointer;
  color: var(--text);
  font-weight: 600;
}

.lab-table-wrap {
  overflow-x: auto;
  margin: 14px 0 6px;
}

.lab-table {
  border-collapse: collapse;
  width: 100%;
  font-size: 0.85rem;
  color: var(--muted);
}

.lab-table caption {
  text-align: left;
  color: var(--text);
  font-weight: 600;
  padding: 6px 0;
}

.lab-table th,
.lab-table td {
  text-align: left;
  padding: 6px 8px;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}

.lab-table th {
  color: var(--text);
  font-weight: 600;
}

.lab-table td.num,
.lab-table th.num {
  text-align: right;
  white-space: nowrap;
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
}

/* ------------------------------------------------ parts and interaction */

/* The first card of each part names the part, so the longer story reads as
   three chapters. */
.lab-step .lab-part {
  border-top: 1px solid var(--line);
  border-radius: var(--radius) var(--radius) 0 0;
  padding-top: 16px;
  font-size: 12px;
  font-weight: 700;
  color: var(--lab-party, var(--text));
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.lab-step .lab-part + .lab-step-num {
  border-top: 0;
  border-radius: 0;
  padding-top: 4px;
}

.lab-step.is-active .lab-part {
  border-color: var(--edge);
}

/* Marks a reader can hover, tap or Tab to (the flow ribbons, the age dots).
   The picked mark is drawn brighter by partyLab.js, so focus needs no ring
   of its own; a keyboard user sees the same highlight and readout. */
.lab-svg .lab-hit {
  cursor: pointer;
  outline: none;
}

.lab-svg .lab-ribbon {
  transition: fill-opacity 0.2s ease, opacity 0.2s ease, stroke 0.2s ease;
}
