/* Lofty Labz: step-built case diagrams.
   Pairs with static/js/diagram.js. The base state here is the NO-JS state: a finished
   diagram and a readable list of its steps. `.is-live` is added only once the script
   has successfully inlined the SVG, so nothing below can hide content from a reader
   whose JS failed. */

.diagram {
  margin: var(--space-4) 0 0;
  border: 1.5px solid var(--near-black);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  background: var(--white);
  overflow: hidden;
}
.diagram .diagram-img,
.diagram .diagram-svg {
  display: block;
  width: 100%;
  height: auto;
  /* Zero CLS: the box is reserved before the SVG arrives (brand-and-frontend.md:26). */
  aspect-ratio: 3 / 2;
  /* Room to breathe. The artwork used to run edge to edge into the card border, so the
     outermost boxes sat with nothing around them and the whole figure read as cramped.
     Padding scales with the viewport so the margin stays proportional rather than
     collapsing on small screens. box-sizing keeps the reserved aspect box honest. */
  padding: clamp(16px, 2.6vw, 40px);
  box-sizing: border-box;
  background: var(--white);
}
.diagram figcaption {
  font-size: var(--step--1);
  color: var(--text-soft);
  padding: var(--space-2) var(--space-3);
  border-top: 1px solid var(--line);
}

/* ---------- the steps, in words ----------
   Without JS this is a plain ordered list under the picture, and it is the whole
   explanation. With JS it becomes the running commentary beside the build. */
.diagram-steps {
  margin: 0;
  /* Roomier than body copy on purpose. These are captions read while watching something
     move, not paragraphs, so they get a wider gutter and more space between them than
     prose would take. */
  padding: var(--space-4) var(--space-5) var(--space-4) calc(var(--space-5) + 1.2em);
  border-top: 1px solid var(--line);
  display: grid;
  gap: var(--space-3);
  font-size: var(--step--1);
  line-height: 1.55;
  color: var(--text-soft);
  background: var(--lavender);
}
.diagram-steps li { margin: 0; }

/* ---------- the note, differentiated ----------
   The step note used to be the same size, family and colour as the body copy above it,
   so while the picture was building the one line that explained it was typographically
   indistinguishable from the paragraph the reader had already finished. It now reads as
   an instrument caption rather than prose: the display family, a tighter tracking, and
   a live marker in the gutter that only the current step carries. */
.diagram.is-live .diagram-steps li {
  opacity: 0.34;
  position: relative;
  /* NOT --ease-out. That token is cubic-bezier(0.2, 0.7, 0.2, 1), which reaches ~90% of
     its value early and then runs an almost flat tail to the end: the same asymptotic
     crawl that was measured and removed from the connector motion in diagram.js. The
     note brightening is half of that same choreographic moment, so it needs a curve with
     a real endpoint slope or the caption visibly hangs while its picture has landed. */
  transition: opacity var(--dur-section) cubic-bezier(0.42, 0, 0.58, 1),
              color var(--dur-section) cubic-bezier(0.42, 0, 0.58, 1);
}
.diagram.is-live .diagram-steps li.is-current {
  opacity: 1;
  color: var(--text);
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: -0.005em;
}
/* The marker sits in the gutter the list padding already reserves, so turning it on
   cannot reflow the text beside it. */
.diagram.is-live .diagram-steps li.is-current::before {
  content: "";
  position: absolute;
  left: calc(-1 * (var(--space-3) + 0.3em));
  top: 0.42em;
  width: 3px;
  height: 1.05em;
  background: var(--purple);
}
@media (prefers-reduced-motion: reduce) {
  .diagram.is-live .diagram-steps li.is-current::before { display: none; }
}

/* ---------- controls ----------
   Real buttons: the diagram must be operable by keyboard and must not depend on
   scrolling to be seen. */
.diagram-controls {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-top: 1px solid var(--line);
  background: var(--lavender-2);
}
.diagram-controls button {
  font: inherit;
  font-size: var(--step--1);
  line-height: 1;
  padding: 8px 12px;
  min-width: 40px;
  min-height: 36px;
  cursor: pointer;
  color: var(--purple);
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius-ctl);
}
.diagram-controls button:hover:not(:disabled) { background: var(--lavender-2); }
.diagram-controls button:disabled { opacity: 0.4; cursor: default; }
.diagram-controls button:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}
.diagram-replay { margin-left: auto; }
.diagram-count {
  font-family: var(--font-display);
  font-size: var(--step--1);
  font-variant-numeric: tabular-nums;
  color: var(--text-soft);
  min-width: 4ch;
  text-align: center;
}

/* ---------- reduced motion ----------
   DESIGN_SPEC §3 and brand-and-frontend.md:30. The script already renders every step
   and every note; this makes sure no transition survives to animate them. */
@media (prefers-reduced-motion: reduce) {
  .diagram.is-live .diagram-steps li { opacity: 1; transition: none; }
  .diagram .diagram-svg [data-step] { opacity: 1 !important; visibility: visible !important; }
  .diagram-controls { display: none; }
}

@media (max-width: 620px) {
  .diagram-controls { flex-wrap: wrap; }
  .diagram-replay { margin-left: 0; }
}
