/* Part 2 — "From human-computer interaction to human-AI interaction" (js/loop/).
 *
 * Visual-first: four drawn cards (tools/loop-art.mjs) round the person in the loop, each
 * captioned by its question. Opening a card (js/loop/explorer.js) shows what the problem means,
 * its Knowledge Work Loop mode and its projects. Baked into index.html by tools/bake-content.mjs.
 * Tokens only, so every look restyles it, drawings included; it sits in @layer engine.
 *
 * Three layouts, by the width Part 2 actually has (container queries, not the viewport):
 *   ≥ 960px  the quad: a 2×2 of cards, each with its inner corner cut round the hub. An opened
 *            card lifts out of its slot onto a stage over the middle of the quad, enlarged, with
 *            its details beside it; the other three recede but stay visible and clickable
 *            (Chris, 2026-10-28: "enlarge the selected card, bring it to front, while still
 *            showing the other cards"). The motion is explorer.js's (WAAPI, one spring).
 *   ≥ 640px  two columns, the hub on top; a card opens in place, below its caption, and the
 *            others fold to their captions.
 *   narrower one column, the hub on top; the same.
 * Without JavaScript every card shows its details inline (the <noscript> rule in the markup).
 */
@layer engine {

@property --loop-lift { syntax: '<number>'; inherits: true; initial-value: 0; }
@property --cut-r { syntax: '<length>'; inherits: true; initial-value: 0px; }

.loop {
  position: relative;
  padding: calc(120px * var(--u-space)) var(--edge) calc(88px * var(--u-space)) var(--edge-text);
  background: var(--work-bg);
  backdrop-filter: blur(var(--work-blur));
  -webkit-backdrop-filter: blur(var(--work-blur));
  color: var(--text);
  /* Small accent text: the accent pulled 18% toward the text colour, so it clears AA where a look's
     accent alone sits just under it (Still Life Opus light). The hue stays the look's. */
  --loop-accent-text: color-mix(in srgb, var(--accent) 82%, var(--text));
  --loop-card: var(--surface);
  --loop-spring: cubic-bezier(0.34, 1.4, 0.64, 1);
  transition: background-color calc(600ms * var(--u-motion)) var(--ease-move);
}
/* With the index published, Part 2 sits on the index's measure; until then it hangs on the
   name's line with the story's close and the footer. */
html:not([data-work='hidden']) .loop {
  padding-left: max(var(--gutter), calc((100% - var(--measure)) / 2));
  padding-right: max(var(--gutter), calc((100% - var(--measure)) / 2));
}
/* No story above (?nostory, or it failed to mount): rise out of the hero instead of starting on a hard edge. */
.hero + .loop::before {
  content: ''; position: absolute; left: 0; right: 0; bottom: 100%; height: calc(160px * var(--u-space));
  background: linear-gradient(to bottom, transparent, var(--work-bg)); pointer-events: none;
}
.loop-inner {
  /* Wide enough for the quad, and no wider than lets the whole loop fit one screen: two card rows
     of 16:9 drawings plus their captions (up to two lines, ~100px each) and the gaps, inside 100svh less the dock. */
  max-width: min(var(--measure), max(960px, calc((100svh - 330px) / 0.5625 + 24px)));
  container: loop / inline-size;
}

/* Part 2's cards are display-only for now: html[data-loop='still'] (the pre-paint default; ?loop=1
   makes them open). No plus, no details, nothing to click; explorer.js refuses to open a card. */
html[data-loop='still'] .loop :is(.loop-plus, .loop-more, .loop-close) { display: none !important; }
html[data-loop='still'] .loop :is(.loop-open, .loop-centre) { pointer-events: none; cursor: default; }

/* Draft gating, as in the story: links into the work only when the work is published. */
html[data-work='hidden'] .loop .work-only { display: none; }
html:not([data-work='hidden']) .loop .work-off { display: none; }

/* ── Head ──────────────────────────────────────────────────────────────────── */
.loop-head { display: grid; gap: calc(18px * var(--u-space)); }
.loop-kicker {
  display: flex; align-items: center; gap: 10px;
  font: 500 12px/1 var(--font-body); letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-2);
}
.loop-draft {
  font: 500 10px/1 var(--font-mono); letter-spacing: 0.08em; padding: 4px 6px; border-radius: calc(4px * var(--u-radius));
  border: 1px solid var(--accent); color: var(--loop-accent-text);
}
.loop-title {
  font-family: var(--font-display); font-weight: 400;
  font-size: calc(clamp(36px, 4.6vw, 68px) * var(--u-type)); line-height: calc(1.02 * var(--u-leading));
  letter-spacing: -0.022em; color: var(--text); max-width: 18ch; text-wrap: balance;
}
.loop-nowrap { white-space: nowrap; }
.loop-intro {
  font-size: calc(18px * var(--u-text)); line-height: calc(1.5 * var(--u-leading)); color: var(--text-2); max-width: 34em;
}
@container loop (min-width: 960px) {
  .loop-head { grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr); column-gap: calc(56px * var(--u-space)); align-items: end; }
  .loop-kicker { grid-column: 1 / -1; }
  .loop-intro { padding-bottom: 0.45em; }
}

/* ── The quad ──────────────────────────────────────────────────────────────── */
.loop-quad {
  --gap: calc(16px * var(--u-space));
  --hub: calc(176px * var(--u-space));
  --loop-mode: stack; /* read by explorer.js: stack (a card opens in place) or stage (it lifts onto the quad) */
  --loop-shadow: 0 2px 6px -2px rgb(0 0 0 / 0.12), 0 30px 64px -26px rgb(0 0 0 / 0.36);
  position: relative; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--gap);
  margin-top: calc(48px * var(--u-space));
  overflow-anchor: none; /* explorer.js holds the scroll itself while cards fold */
}
[data-theme='dark'] .loop-quad { --loop-shadow: 0 2px 8px -2px rgb(0 0 0 / 0.45), 0 34px 76px -24px rgb(0 0 0 / 0.72); }
.loop-card {
  position: relative; isolation: isolate; display: flex; flex-direction: column; min-width: 0;
  border-radius: var(--radius-lg);
  --cut-r: var(--notch, 0px);
  transform-origin: var(--ox, 50% 0%);
  transition: scale calc(620ms * var(--u-motion)) var(--loop-spring), --cut-r calc(420ms * var(--u-motion)) var(--ease-move);
}
/* The card's face is a layer of its own, so on the quad the cut can take it (and the drawing),
   and so an opened card can leave it behind as the empty slot it lifted out of. */
.loop-card::before {
  content: ''; position: absolute; inset: 0; z-index: -1; border-radius: inherit; pointer-events: none;
  background: var(--loop-card); box-shadow: inset 0 0 0 1px var(--line); border: 1px dashed transparent;
  transition: box-shadow calc(260ms * var(--u-motion)) var(--ease-enter), background-color calc(420ms * var(--u-motion)) var(--ease-move), border-color calc(420ms * var(--u-motion)) var(--ease-move);
}
.loop-card:hover::before { box-shadow: inset 0 0 0 1px var(--line-strong); }
.loop-card:focus-within::before { box-shadow: inset 0 0 0 1.5px var(--accent); }
.loop-card.is-open::before { box-shadow: inset 0 0 0 1.5px var(--accent), var(--loop-shadow); }

/* Closed, the sheet and the stage add nothing: the face is the card. */
.loop-sheet, .loop-stage { display: contents; }
.loop-face {
  position: relative; display: grid; grid-template-rows: 1fr auto; min-width: 0;
  transition: grid-template-rows calc(560ms * var(--u-motion)) var(--ease-move);
}
.loop-art {
  position: relative; min-height: 0; overflow: hidden; border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  transition: opacity calc(420ms * var(--u-motion)) var(--ease-move);
}
.loop-svg {
  width: 100%; height: auto; aspect-ratio: 480 / 270; overflow: visible;
  transform-origin: 50% 60%; transition: scale calc(700ms * var(--u-motion)) var(--loop-spring);
}
.loop-card:hover .loop-svg { scale: 1.025; }

.loop-cap {
  display: grid; gap: 6px; align-content: start;
  padding: calc(14px * var(--u-space)) calc(20px * var(--u-space)) calc(18px * var(--u-space));
}
.loop-card-kicker {
  display: flex; align-items: baseline; gap: 10px;
  font: 500 11.5px/1.2 var(--font-mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-2);
}
.loop-num { font: 500 11.5px/1 var(--font-mono); letter-spacing: 0.04em; color: var(--loop-accent-text); }
.loop-q { font: inherit; }
.loop-open {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; width: 100%; text-align: left;
  font-family: var(--font-display); font-weight: 400;
  font-size: calc(clamp(17px, 1.3vw, 20px) * var(--u-type)); line-height: 1.22; letter-spacing: -0.01em; color: var(--text);
}
/* The whole face opens it. */
.loop-open::after { content: ''; position: absolute; inset: 0; z-index: 1; border-radius: inherit; }
.loop-open:focus-visible { outline: none; }
.loop-open:focus-visible .loop-q-text { text-decoration: underline; text-decoration-color: var(--accent); text-underline-offset: 4px; text-decoration-thickness: 2px; }
.loop-q-text { text-wrap: balance; }
.loop-plus {
  flex: none; width: 30px; height: 30px; margin-top: -3px; padding: 7px; border-radius: 50%;
  fill: none; stroke: var(--text); stroke-width: 1.6; stroke-linecap: round;
  box-shadow: inset 0 0 0 1px var(--line-strong); background: var(--bg);
  transition: rotate calc(520ms * var(--u-motion)) var(--loop-spring), scale calc(420ms * var(--u-motion)) var(--loop-spring), opacity calc(200ms * var(--u-motion)) var(--ease-enter), background-color var(--dur-fast) var(--ease-enter), stroke var(--dur-fast) var(--ease-enter), box-shadow var(--dur-fast);
}
.loop-card:hover .loop-plus { background: var(--accent); stroke: var(--accent-ink); box-shadow: none; }
.loop-card.is-open .loop-plus { rotate: 45deg; }

/* One open: the other three fold to their captions, still there to switch to. */
.loop-quad[data-open] .loop-card:not(.is-open, .is-closing) .loop-face { grid-template-rows: 0fr auto; }
.loop-quad[data-open] .loop-card:not(.is-open, .is-closing) .loop-art { opacity: 0; }

/* ── Details ───────────────────────────────────────────────────────────────── */
.loop-more { display: grid; grid-template-rows: 0fr; visibility: hidden; position: relative; z-index: 2;
  transition: grid-template-rows calc(520ms * var(--u-motion)) var(--ease-move), visibility 0s linear calc(520ms * var(--u-motion)); }
.loop-more-inner { min-height: 0; overflow: hidden; padding-bottom: calc(22px * var(--u-space)); }
.loop-card.is-open .loop-more { grid-template-rows: 1fr; visibility: visible; transition: grid-template-rows calc(560ms * var(--u-motion)) var(--ease-move), visibility 0s; }
.loop-more-inner > * { margin-inline: calc(20px * var(--u-space)); }
.loop-more-head { display: none; }
.loop-close {
  position: relative; z-index: 1; flex: none; width: 36px; height: 36px; padding: 9px; border-radius: 50%;
  box-shadow: inset 0 0 0 1px var(--line-strong); background: var(--bg);
  transition: background-color var(--dur-fast) var(--ease-enter), box-shadow var(--dur-fast) var(--ease-enter), scale calc(420ms * var(--u-motion)) var(--loop-spring);
}
.loop-close svg { width: 100%; height: 100%; fill: none; stroke: var(--text); stroke-width: 1.6; stroke-linecap: round; }
.loop-close:hover { background: var(--surface-2); box-shadow: inset 0 0 0 1.5px var(--accent); scale: 1.06; }
.loop-close:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.loop-text { display: grid; gap: calc(8px * var(--u-space)); padding-top: calc(4px * var(--u-space)); }
.loop-text p, .loop-kwl { font-size: calc(15px * var(--u-text)); line-height: calc(1.55 * var(--u-leading)); color: var(--text-2); }
.loop-kwl { margin-top: calc(14px * var(--u-space)); padding-top: calc(12px * var(--u-space)); border-top: 1px solid var(--line); }
.loop-kwl strong { font-weight: 600; color: var(--text); }
.loop-label {
  display: block; margin-bottom: 4px;
  font: 500 10.5px/1.2 var(--font-mono); letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-2);
}
.loop-research { margin-top: calc(12px * var(--u-space)); font-size: calc(14px * var(--u-text)); color: var(--text); }
.loop-research .loop-label { display: inline; margin: 0 10px 0 0; }

/* Projects: chips, an icon for the kind of work. */
.loop-projects { display: flex; flex-wrap: wrap; gap: 8px; margin-top: calc(14px * var(--u-space)); }
.loop-proj { display: contents; }
.loop-chip {
  display: inline-flex; align-items: center; gap: 10px; min-height: 40px; max-width: 100%;
  padding: 6px 14px 6px 8px; border-radius: 999px; background: var(--bg); box-shadow: inset 0 0 0 1px var(--line-strong);
  color: var(--text); font-size: calc(14px * var(--u-text)); line-height: 1.25;
  transition: box-shadow var(--dur-fast) var(--ease-enter), background-color var(--dur-fast) var(--ease-enter), translate calc(420ms * var(--u-motion)) var(--loop-spring);
}
.loop-proj-named .loop-chip { border-radius: calc(14px * var(--u-radius)); padding-block: 8px; }
.loop-chip-icon {
  flex: none; width: 26px; height: 26px; padding: 4px; border-radius: 50%;
  background: color-mix(in srgb, var(--accent) 16%, var(--bg)); fill: none; stroke: var(--text); stroke-width: 1.4; stroke-linecap: round; stroke-linejoin: round;
}
.loop-chip-text { display: grid; gap: 1px; min-width: 0; }
.loop-chip-name { font-weight: 600; }
.loop-proj-note { font-size: calc(12.5px * var(--u-text)); color: var(--text-2); }
a.loop-chip:hover { box-shadow: inset 0 0 0 1.5px var(--accent); translate: 0 -1px; }
a.loop-chip .icon-arrow { flex: none; color: var(--text-2); }

.loop-plate { margin-top: calc(14px * var(--u-space)); border-radius: var(--radius-md); overflow: hidden; box-shadow: inset 0 0 0 1px var(--line); background: var(--bg); }
.loop-plate img { width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover; object-position: top left; }
.loop-cta { margin-top: calc(12px * var(--u-space)); }
.loop-cta a {
  display: inline-flex; align-items: center; gap: 8px; font-weight: 500; font-size: calc(14.5px * var(--u-text)); color: var(--text);
  text-decoration: underline; text-decoration-color: var(--line-strong); text-underline-offset: 3px;
  transition: text-decoration-color var(--dur-fast) var(--ease-enter);
}
.loop-cta a:hover { text-decoration-color: var(--accent); }
.loop-count { font: 400 12px/1 var(--font-mono); color: var(--text-2); }

/* ── The hub: the person in the loop ───────────────────────────────────────── */
.loop-hub {
  position: relative; justify-self: center; width: var(--hub); aspect-ratio: 1; z-index: 3; pointer-events: none;
  margin-block: calc(4px * var(--u-space)) calc(8px * var(--u-space));
}
.loop-hub-svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.loop-track { fill: none; stroke: var(--line-strong); stroke-width: 1.25; }
.loop-arc { fill: none; stroke: var(--accent); stroke-width: 3.5; stroke-linecap: round; }
.loop-chev { fill: none; stroke: var(--text-2); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.loop-comet { fill: var(--accent); }
.loop-comet-2 { fill: var(--text-2); }
.loop[data-still] .loop-comet { display: none; }
.loop-centre {
  position: absolute; inset: 18%; pointer-events: auto;
  display: grid; place-content: center; justify-items: center; gap: 4px; text-align: center;
  border-radius: 50%; background: var(--bg); box-shadow: inset 0 0 0 1px var(--line-strong), 0 1px 0 var(--line);
  color: var(--text);
  transition: box-shadow var(--dur-fast) var(--ease-enter), scale calc(520ms * var(--u-motion)) var(--loop-spring), background-color calc(300ms * var(--u-motion)) var(--ease-enter);
}
.loop-centre:hover { box-shadow: inset 0 0 0 1.5px var(--accent); scale: 1.04; }
.loop-centre[aria-pressed='true'] { background: color-mix(in srgb, var(--accent) 12%, var(--bg)); box-shadow: inset 0 0 0 1.5px var(--accent); }
.loop-person { width: 30%; height: auto; fill: none; stroke: var(--text); stroke-width: 2; stroke-linecap: round; }
.loop-person circle { fill: color-mix(in srgb, var(--accent) 40%, var(--bg)); }
.loop-centre-label { font: 600 calc(11.5px * var(--u-text))/1.15 var(--font-body); max-width: 9ch; letter-spacing: 0.01em; }

/* ── Two columns ───────────────────────────────────────────────────────────── */
@container loop (min-width: 640px) {
  .loop-quad { grid-template-columns: repeat(2, minmax(0, 1fr)); --gap: calc(20px * var(--u-space)); }
  .loop-hub { grid-column: 1 / -1; }
}
@container loop (640px <= width < 960px) {
  /* An open card's row partner folds to its caption instead of stretching to the open card. */
  .loop-quad[data-open] .loop-card:not(.is-open) { align-self: start; }
}

/* ── The quad: a 2×2 round the hub, each inner corner cut by it ────────────── */
@container loop (min-width: 960px) {
  .loop-quad {
    --loop-mode: stage;
    --gap: calc(24px * var(--u-space));
    --notch: calc(var(--hub) / 2 + 14px);
    --hub: calc(184px * var(--u-space));
    grid-template-rows: 1fr 1fr; margin-top: calc(56px * var(--u-space));
  }
  .loop-hub { position: absolute; left: 50%; top: 50%; translate: -50% -50%; margin: 0; }
  /* Every card has its own slot, so one lifting out never lets another slide into it. Each
     recedes toward its outer corner, keeping its caption where it was. */
  .loop-card[data-n='1'] { grid-area: 1 / 1; --ox: 0% 0%; }
  .loop-card[data-n='2'] { grid-area: 1 / 2; --ox: 100% 0%; }
  .loop-card[data-n='3'] { grid-area: 2 / 2; --ox: 100% 100%; }
  .loop-card[data-n='4'] { grid-area: 2 / 1; --ox: 0% 100%; }
  .loop-face { display: flex; flex-direction: column; flex: 1 1 auto; }
  /* Top row: caption above, drawing below (toward the hub). Bottom row: the reverse. */
  .loop-card[data-n='1'] .loop-cap, .loop-card[data-n='2'] .loop-cap { order: -1; padding-bottom: calc(6px * var(--u-space)); }
  .loop-card[data-n='1'] .loop-art, .loop-card[data-n='2'] .loop-art { margin-top: auto; border-radius: 0 0 var(--radius-lg) var(--radius-lg); }
  .loop-card[data-n='3'] .loop-cap, .loop-card[data-n='4'] .loop-cap { padding-top: calc(6px * var(--u-space)); }
  .loop-card {
    --cx: calc(100% + var(--gap) / 2); --cy: calc(100% + var(--gap) / 2);
    --cut: radial-gradient(circle at var(--cx) var(--cy), transparent var(--cut-r), #000 calc(var(--cut-r) + 0.75px));
  }
  /* The drawing shares its card's inner corner (it sits against the hub side), so one cut fits both. */
  .loop-card::before, .loop-card .loop-art { -webkit-mask: var(--cut); mask: var(--cut); }
  .loop-card[data-n='2'] { --cx: calc(var(--gap) / -2); }
  .loop-card[data-n='3'] { --cx: calc(var(--gap) / -2); --cy: calc(var(--gap) / -2); }
  .loop-card[data-n='4'] { --cy: calc(var(--gap) / -2); }
  .loop-more { display: none; } /* closed, the details wait on the stage */

  /* The other three recede: a touch smaller, their drawings dimmed, captions untouched (still AA). */
  .loop-quad[data-open] .loop-card:not(.is-open, .is-closing) { scale: 0.965; }
  .loop-quad[data-open] .loop-card:not(.is-open, .is-closing) .loop-face { grid-template-rows: none; }
  .loop-quad[data-open] .loop-card:not(.is-open, .is-closing) .loop-art { opacity: 0.4; }
  .loop-quad[data-open] .loop-card:not(.is-open, .is-closing):is(:hover, :focus-within) { scale: 0.985; }
  .loop-quad[data-open] .loop-card:not(.is-open, .is-closing):is(:hover, :focus-within) .loop-art { opacity: 0.75; }

  /* Lifted: the card leaves its slot for a stage over the middle of the quad. Every length here
     is measured by explorer.js (stage()) and written on the card in px:
       --ql/--qt/--qw/--qh  the quad, from the card   the sheet covers it and is clipped to the stage
       --clip-open          the stage, as an inset()  the sheet's clip when open
       --sx/--sy/--sw/--sh  the stage, in the quad    where the face and the details are laid out
       --fx/--fy/--fw/--fh/--fk  the face: its place on the stage, its slot size and its scale
       --dx --pad           where the details start, and the stage's padding
       --ax/--ay/--aw/--ah  the stage, from the card  the ring and shadow (::after)
     Opening animates the sheet's clip from the slot to the stage, the face from its slot to its
     place and the ring with them (one spring); the details fade in behind. */
  .loop-card:is(.is-open, .is-closing) { z-index: 5; min-height: var(--fh); transition: --cut-r calc(420ms * var(--u-motion)) var(--ease-move); }
  .loop-card.is-closing { z-index: 4; }
  .loop-card.is-open { --cut-r: 0px; }
  .loop-card.is-open::before { background-color: transparent; box-shadow: none; border-color: var(--line-strong); }
  .loop-card:is(.is-open, .is-closing)::after {
    content: ''; position: absolute; z-index: 2; pointer-events: none;
    left: var(--ax); top: var(--ay); width: var(--aw); height: var(--ah); transform-origin: 0 0;
    border-radius: var(--radius-lg); box-shadow: inset 0 0 0 1.5px var(--accent), var(--loop-shadow);
  }
  .loop-card:is(.is-open, .is-closing) .loop-sheet {
    display: block; position: absolute; z-index: 1;
    left: var(--ql); top: var(--qt); width: var(--qw); height: var(--qh);
    background: var(--loop-card); clip-path: var(--clip-open);
  }
  .loop-card:is(.is-open, .is-closing) .loop-stage { display: block; position: absolute; left: var(--sx); top: var(--sy); width: var(--sw); height: var(--sh); }
  .loop-card:is(.is-open, .is-closing) .loop-face {
    position: absolute; left: var(--fx); top: var(--fy); width: var(--fw); height: var(--fh);
    transform-origin: 0 0; transform: scale(var(--fk));
  }
  .loop-card:is(.is-open, .is-closing) .loop-open::after { content: none; }
  .loop-card.is-open .loop-plus { opacity: 0; scale: 0.6; }
  .loop-card:is(.is-open, .is-closing) .loop-more {
    display: block; position: absolute; left: var(--dx); top: 0; right: 0; bottom: 0; visibility: visible;
    overflow: auto; overscroll-behavior: contain; scrollbar-width: thin; scrollbar-color: var(--line-strong) transparent;
  }
  .loop-card:is(.is-open, .is-closing) .loop-more[data-below] { mask-image: linear-gradient(to bottom, #000 calc(100% - 48px), transparent); }
  .loop-card:is(.is-open, .is-closing) .loop-more-inner { overflow: visible; min-height: 0; padding: var(--dt) var(--pad) var(--pad) 0; }
  .loop-card:is(.is-open, .is-closing) .loop-more-inner > * { margin-inline: 0; }
  /* Close sits in the stage's corner and stays there while the details scroll under it: a
     sticky head of no height, stuck where the text starts, its button lifted to the corner. */
  .loop-card:is(.is-open, .is-closing) .loop-more-head {
    position: sticky; top: var(--dt); z-index: 1; display: flex; justify-content: flex-end; height: 0;
    margin-right: calc(12px - var(--pad));
  }
  .loop-card:is(.is-open, .is-closing) .loop-close { margin-top: calc(12px - var(--dt)); }
  .loop-card:is(.is-open, .is-closing) .loop-text { padding-top: 0; }
  .loop-card:is(.is-open, .is-closing) .loop-text p:first-child { font-size: calc(16.5px * var(--u-text)); color: var(--text); }
}

/* ── Phones ────────────────────────────────────────────────────────────────── */
@media (max-width: 759px) {
  .loop { padding-top: calc(88px * var(--u-space)); padding-bottom: calc(64px * var(--u-space)); }
  .loop-title { font-size: calc(clamp(32px, 9vw, 42px) * var(--u-type)); }
  .loop-intro { font-size: calc(16.5px * var(--u-text)); }
}

/* ── The drawings ──────────────────────────────────────────────────────────── */
.loop-svg { --lv-faint: color-mix(in srgb, var(--text) 20%, transparent); --lv-tint: color-mix(in srgb, var(--accent) 16%, var(--bg)); }
.loop-svg .lv-card { fill: var(--bg); stroke: var(--line-strong); stroke-width: 1; }
.loop-svg .lv-card2 { fill: var(--surface-2); }
.loop-svg .lv-edge { stroke: var(--line-strong); stroke-width: 1; }
.loop-svg .lv-edge-acc { stroke: var(--accent); stroke-width: 1.5; }
.loop-svg .lv-acc { fill: var(--accent); }
.loop-svg .lv-on-acc { fill: var(--accent-ink); }
.loop-svg .lv-ink-f { fill: var(--text-2); }
.loop-svg .lv-faint-f { fill: var(--lv-faint); }
.loop-svg .lv-tint { fill: var(--lv-tint); }
.loop-svg .lv-hill { fill: color-mix(in srgb, var(--accent) 42%, var(--bg)); }
.loop-svg .lv-type { font: 400 34px/1 var(--font-display); fill: var(--text); }
.loop-svg .lv-tick { fill: none; stroke: var(--accent); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.loop-svg .lv-thread { fill: none; stroke: var(--line-strong); stroke-width: 1.1; stroke-dasharray: 2 3.5; }
.loop-svg .lv-packet, .loop-svg .lv-sap { fill: var(--accent); }
.loop-svg .lv-fold { fill: var(--surface-2); stroke: var(--line-strong); stroke-width: 1; stroke-linejoin: round; }
.loop-svg .lv-arrow { fill: none; stroke: var(--text-2); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.loop-svg .lv-glow { fill: var(--accent); opacity: 0.14; }
.loop-svg .lv-body { fill: var(--surface-2); stroke: var(--text); stroke-width: 1.3; stroke-linejoin: round; }
.loop-svg [data-bob] .lv-body { fill: color-mix(in srgb, var(--accent) 55%, var(--bg)); }
.loop-svg .lv-glass { fill: var(--lv-tint); }
.loop-svg .lv-knot { fill: none; stroke-width: 2.4; stroke: var(--text); }
.loop-svg .lv-eye { fill: var(--text); }
.loop-svg .lv-spark { fill: var(--accent); }
.loop-svg .lv-facet { fill: none; stroke: var(--text); stroke-width: 0.8; opacity: 0.6; }
.loop-svg .lv-mote { fill: var(--text-2); }
.loop-svg .lv-orbit { fill: none; stroke: var(--line-strong); stroke-width: 1; stroke-dasharray: 3 4; }
.loop-svg .lv-spoke { stroke: var(--line); stroke-width: 1; }
.loop-svg .lv-ring { fill: none; stroke: var(--text); stroke-width: 1.4; }
.loop-svg .lv-ring-back { opacity: 0.45; }
.loop-svg .lv-tag { fill: var(--lv-faint); }
.loop-svg .lv-ground { stroke: var(--line-strong); stroke-width: 1.4; stroke-linecap: round; }
.loop-svg .lv-soil { stroke: var(--line); stroke-width: 1.2; stroke-linecap: round; }
.loop-svg .lv-stem { fill: none; stroke: var(--text-2); stroke-width: 2.6; stroke-linecap: round; }
.loop-svg .lv-branch { fill: none; stroke: var(--text-2); stroke-width: 1.8; stroke-linecap: round; }
.loop-svg .lv-leaf { fill: color-mix(in srgb, var(--accent) 48%, var(--bg)); stroke: var(--accent); stroke-width: 1; }
.loop-svg .lv-vein { fill: none; stroke: var(--bg); stroke-width: 0.9; stroke-linecap: round; }
.loop-svg .lv-tab-on { fill: var(--text); }
.loop-svg .lv-mono { font: 500 9.5px/1 var(--font-mono); fill: var(--text-2); }
.loop-svg .lv-mono-on { fill: var(--bg); }
.loop-svg .lv-leader { fill: none; stroke: var(--accent); stroke-width: 1.2; stroke-dasharray: 3 3; }
.loop-svg .lv-pin-n { font: 700 10px/1 var(--font-mono); fill: var(--accent-ink); }
.loop-svg .lv-check { fill: none; stroke: var(--accent-ink); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.loop-svg .lv-cursor { fill: var(--text); stroke: var(--bg); stroke-width: 1; stroke-linejoin: round; }

/* ── Reduced motion: everything still, nothing springs ─────────────────────── */
.loop[data-still] :is(.loop-svg, .loop-plus, .loop-more, .loop-centre, .loop-chip, .loop-card, .loop-face, .loop-close) { transition: none !important; }
.loop[data-still] .loop-quad[data-open] .loop-card { scale: none !important; }

} /* @layer engine */
