/* ==========================================================================
   bimon.net - components
   Hero, work index, cursor preview, cards, lab, notes, about, editorial prose.
   ========================================================================== */

/* ---------- eyebrow ----------
   A mono label with a small filled square. Used to open every major block so
   the reader always knows what they are looking at. */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.55em;
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: var(--tracking-mono);
  text-transform: uppercase;
  color: var(--ink-dim);
  font-weight: 500;
}
.eyebrow::before {
  content: "";
  width: 0.45em; height: 0.45em;
  background: var(--accent);
  flex: none;
}
.eyebrow--plain::before { display: none; }

/* ---------- hero ---------- */
.hero { padding-block: clamp(2.5rem, 11vh, 7rem) clamp(2rem, 5vh, 3.5rem); }
.hero__capabilities { margin-top: clamp(2rem, 6vh, 4rem); }
.hero__eyebrow { margin-bottom: var(--s-m); }
.hero__title {
  font-family: var(--font-display);
  font-size: var(--step-5);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-display);
  max-width: 16ch;
  margin-bottom: var(--s-m);
}
.hero__title em {
  font-style: italic;
  color: var(--accent);
}
.hero__deck {
  font-size: var(--step-1);
  line-height: 1.5;
  color: var(--ink-2);
  max-width: var(--measure-narrow);
  letter-spacing: -0.005em;
  margin-bottom: var(--s-l);
}
.hero__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-xs) var(--s-m);
  padding-top: var(--s-s);
  border-top: 1px solid var(--line);
  max-width: 46rem;
}
.status { display: inline-flex; align-items: center; gap: 0.5em; }
/* A dot that breathes: the only looping animation on the site, and it is
   small enough to read as a heartbeat rather than a distraction. */
.status__dot {
  width: 0.5em; height: 0.5em;
  border-radius: var(--r-full);
  background: var(--accent);
  box-shadow: 0 0 0 0 var(--accent-soft);
  animation: pulse 2.8s var(--ease-in-out) infinite;
}
@keyframes pulse {
  0%, 100% { box-shadow: 0 0 0 0 var(--accent-soft); }
  50%      { box-shadow: 0 0 0 0.45em transparent; }
}

/* ---------- page head (sub pages) ---------- */
.page-head { padding-block: clamp(3rem, 10vh, 6.5rem) clamp(2rem, 5vh, 3.5rem); }
.page-head__title {
  font-family: var(--font-display);
  font-size: var(--step-4);
  line-height: 1.02;
  letter-spacing: var(--tracking-display);
  margin-block: var(--s-s) var(--s-m);
  max-width: 22ch;
}
.page-head__deck { max-width: var(--measure); color: var(--ink-2); font-size: var(--step-1); line-height: 1.5; }

/* ---------- project dossiers ----------
   Two lines per project: the claim, then the specifics. A numbered list is
   faster to scan and carries more work per screen than a card grid, which is
   what the reference portfolios do instead of thumbnail walls. The screenshot
   is revealed on pointer-over so the list stays light on a phone. */
.work-index { border-top: 1px solid var(--line); }
.dossier {
  position: relative;
  display: grid;
  grid-template-columns: 3.25rem minmax(0, 1fr) auto;
  align-items: start;
  gap: var(--s-2xs) var(--s-m);
  padding-block: clamp(1.1rem, 2.6vw, 1.8rem);
  border-bottom: 1px solid var(--line);
  color: inherit;
  text-decoration: none;
  isolation: isolate;
}
.dossier::before {
  content: "";
  position: absolute;
  inset: 0 calc(var(--gutter) * -0.35);
  background: var(--bg-elev);
  z-index: -1;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-3) var(--ease-out-quint);
}
.dossier:hover::before, .dossier:focus-visible::before { transform: scaleX(1); }
.dossier__index {
  font-family: var(--font-mono);
  font-size: var(--step--2);
  color: var(--ink-dim);
  font-variant-numeric: tabular-nums;
  padding-top: 0.55em;
  transition: color var(--dur-2) var(--ease-swift);
}
.dossier__body { display: flex; flex-direction: column; gap: 0.4rem; min-width: 0; }
.dossier__title {
  display: flex;
  align-items: baseline;
  gap: 0.65em;
  flex-wrap: wrap;
  font-size: var(--step-2);
  line-height: 1.16;
  letter-spacing: var(--tracking-tight);
  transition: transform var(--dur-3) var(--ease-out-quint);
}
.dossier__desc { color: var(--ink-dim); font-size: var(--step--1); line-height: 1.55; max-width: 62ch; }
.dossier__meta {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.35rem;
  text-align: right;
  white-space: nowrap;
  padding-top: 0.35rem;
}
.dossier:hover .dossier__index, .dossier:focus-visible .dossier__index { color: var(--accent); }
.dossier:hover .dossier__title, .dossier:focus-visible .dossier__title { transform: translateX(0.4rem); }

/* Status is a fact, so it gets a factual label and a small tone marker
   rather than an adjective. */
.chip--live { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 42%, transparent); }
.chip--running { color: var(--ink-2); border-color: var(--line-strong); }

/* Cursor-following preview of the real product screenshot. */
.work-preview {
  position: fixed;
  top: 0; left: 0;
  z-index: var(--z-preview);
  width: clamp(240px, 24vw, 380px);
  aspect-ratio: 16 / 10;
  pointer-events: none;
  opacity: 0;
  transform: translate3d(var(--px, 0px), var(--py, 0px), 0) translate(-50%, -50%) scale(0.94) rotate(-1.5deg);
  transition: opacity var(--dur-3) var(--ease-out-quint), transform var(--dur-3) var(--ease-out-quint);
  overflow: hidden;
  border-radius: var(--r-1);
  box-shadow: var(--shadow-2);
  background: var(--bg-sunken);
}
.work-preview[data-visible="true"] { opacity: 1; transform: translate3d(var(--px, 0px), var(--py, 0px), 0) translate(-50%, -50%) scale(1) rotate(-1.5deg); }
.work-preview img { width: 100%; height: 100%; object-fit: cover; }
@media (hover: none), (pointer: coarse), (max-width: 900px) { .work-preview { display: none; } }

/* ---------- facts strip ----------
   Numbers instead of adjectives: the first thing after the claim is evidence.
   A rules-banded band, no card, no shadow. */
.section--facts {
  padding-block: clamp(1.75rem, 4vh, 2.75rem);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
.facts-strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--s-m) var(--s-l);
}
.fact { display: flex; flex-direction: column; gap: 0.35rem; }
.fact__value {
  font-family: var(--font-display);
  font-size: clamp(2.6rem, 1.4rem + 3.4vw, 4rem);
  line-height: 0.9;
  letter-spacing: var(--tracking-display);
  display: flex;
  align-items: baseline;
  gap: 0.25em;
}
.fact__unit {
  font-family: var(--font-mono);
  font-size: var(--step--1);
  letter-spacing: var(--tracking-mono);
  text-transform: uppercase;
  color: var(--ink-dim);
}
.fact__label { color: var(--ink-dim); }

/* ---------- mechanism diagrams ----------
   Inline SVG on purpose: it inherits the site's custom properties, so light and
   dark need no second asset, and the labels stay real selectable text rather
   than pixels. Two orientations are emitted and CSS picks one, because a
   1200px left-to-right flow scaled onto a phone is unreadable. */
/* A diagram inside .prose would be clamped to the 68ch text measure (~688px),
   which scales the wide SVG to about 0.58 and makes 12.5px labels render at
   ~7px. Break it out to the container content box instead: .prose starts at the
   same left edge, so this only needs a width, no offset. */
.diagram {
  margin-block: var(--s-xl);
  width: min(calc(100vw - 2 * var(--gutter)), calc(var(--page-max) - 2 * var(--gutter)));
  max-width: none;
}
.diagram__lang { display: block; }
.diagram__svg { display: block; width: 100%; height: auto; }
.diagram__svg--tall { display: none; }
@media (max-width: 780px) {
  .diagram__svg--wide { display: none; }
  .diagram__svg--tall { display: block; }
}
.dg-node { fill: var(--bg-elev); stroke: var(--line-strong); stroke-width: 1.5; }
.dg-node--accent { fill: var(--accent-soft); stroke: var(--accent); }
.dg-node--muted { fill: none; stroke: var(--line-strong); stroke-dasharray: 6 5; }
.dg-mark { fill: var(--line-strong); }
.dg-mark--accent { fill: var(--accent); }
.dg-edge { stroke: var(--line-strong); stroke-width: 1.5; fill: none; }
.dg-edge--accent { stroke: var(--accent); }
.dg-head { font-family: var(--font-display); font-size: 27px; fill: var(--ink); letter-spacing: -0.02em; }
.dg-lede { font-family: var(--font-mono); font-size: 13px; fill: var(--ink-dim); letter-spacing: 0.02em; }
.dg-title { font-family: var(--font-sans); font-size: 18px; font-weight: 500; fill: var(--ink); letter-spacing: -0.012em; }
.dg-sub { font-family: var(--font-mono); font-size: 12.5px; fill: var(--ink-dim); }
.dg-note { font-family: var(--font-mono); font-size: 12px; fill: var(--ink-dim); }
.dg-note--accent { fill: var(--accent); }
.dg-edge-label { font-family: var(--font-mono); font-size: 11.5px; fill: var(--ink-dim); letter-spacing: 0.04em; }
/* the tall variant has a much narrower viewBox, so its headings need to be
   smaller to stay inside it */
.diagram__svg--tall .dg-head { font-size: 22px; }
.diagram__svg--tall .dg-lede { font-size: 12px; }
.diagram__cap {
  margin-top: 0.9rem;
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.03em;
  color: var(--ink-dim);
  max-width: 64ch;
}

/* ---------- workbench band ----------
   One wide object built from his own screenshots: a specimen sheet of the three
   kinds of work, hairline-separated, no shadow. Gives the top of the homepage a
   visual anchor instead of another paragraph. */
.section--bench { padding-block: clamp(2rem, 5vh, 3.25rem); }
.bench {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--r-1);
  overflow: hidden;
}
.bench__item { margin: 0; background: var(--bg); display: flex; flex-direction: column; }
.bench__item img {
  width: 100%;
  height: clamp(190px, 23vw, 330px);
  object-fit: cover;
  object-position: top center;
  display: block;
  background: var(--bg-sunken);
}
.bench__item figcaption {
  padding: 0.7rem 0.95rem 0.85rem;
  border-top: 1px solid var(--line);
  color: var(--ink-dim);
}
/* The field band holds photographs rather than screenshots, so it gets more
   height and crops from the middle instead of the top. */
.bench--field .bench__item img { height: clamp(200px, 25vw, 360px); object-position: center 40%; }
@media (max-width: 860px) {
  .bench { grid-template-columns: 1fr; }
  .bench__item img { height: auto; aspect-ratio: 16 / 10; }
}

/* ---------- data table ---------- */
/* Same break-out as .diagram: inside .prose the table would be clamped to the
   68ch measure, leaving half the page empty and squeezing six columns. */
.datatable {
  margin-block: var(--s-xl);
  width: min(calc(100vw - 2 * var(--gutter)), calc(var(--page-max) - 2 * var(--gutter)));
  max-width: none;
}
.datatable__scroll {
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--r-1);
  -webkit-overflow-scrolling: touch;
}
.datatable table {
  width: 100%;
  min-width: 660px;
  border-collapse: collapse;
  font-size: var(--step--1);
}
.datatable th {
  text-align: left;
  padding: 0.62rem 0.8rem;
  border-bottom: 1px solid var(--line-strong);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: var(--tracking-mono);
  text-transform: uppercase;
  color: var(--ink-dim);
  white-space: nowrap;
}
.datatable td {
  padding: 0.5rem 0.8rem;
  border-bottom: 1px solid var(--line);
  color: var(--ink-2);
  vertical-align: top;
}
.datatable tbody tr:last-child td { border-bottom: 0; }
.datatable tbody tr:hover td { background: var(--bg-elev); color: var(--ink); }
.datatable td.num {
  text-align: right;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  white-space: nowrap;
}
.datatable figcaption {
  margin-top: 0.7rem;
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.03em;
  color: var(--ink-dim);
  max-width: 64ch;
}

/* ---------- capability blocks ---------- */
.cap-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr));
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--r-1);
  overflow: hidden;
}
.cap {
  background: var(--bg);
  padding: var(--s-m);
  display: flex;
  flex-direction: column;
  gap: var(--s-xs);
  min-height: 13rem;
}
.cap__title { font-size: var(--step-1); letter-spacing: var(--tracking-tight); }
.cap__desc { color: var(--ink-dim); font-size: var(--step--1); line-height: 1.6; }
.cap .chip-list { margin-top: auto; }

/* ---------- dated build log ----------
   Mono date in its own column so the chronology is scannable without reading
   the sentences. */
.log { display: flex; flex-direction: column; border-top: 1px solid var(--line); }
.log__item {
  display: grid;
  grid-template-columns: 9rem minmax(0, 1fr);
  gap: var(--s-s) var(--s-m);
  padding-block: clamp(0.9rem, 2.2vw, 1.35rem);
  border-bottom: 1px solid var(--line);
}
.log__when { padding-top: 0.35em; color: var(--ink-dim); }
.log__body { display: flex; flex-direction: column; gap: 0.3rem; }
.log__title { font-size: var(--step-1); letter-spacing: var(--tracking-tight); }
.log__text { color: var(--ink-dim); font-size: var(--step--1); line-height: 1.6; max-width: 66ch; }

/* ---------- screenshot gallery ---------- */
.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
  gap: var(--s-m);
}
.gallery__item { margin: 0; }
.gallery__item img {
  width: 100%;
  height: auto;
  border-radius: var(--r-1);
  border: 1px solid var(--line);
  background: var(--bg-sunken);
}
.gallery__item figcaption {
  margin-top: 0.6rem;
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.03em;
  color: var(--ink-dim);
}

/* "Right now" card. A real screenshot of the current project instead of a
   fabricated portrait - a stock or invented face on a personal site is a
   liability, and this is more informative anyway. */
.now-card { margin: 0; display: flex; flex-direction: column; gap: 0.6rem; }
.now-card img { width: 100%; height: auto; border-radius: var(--r-1); border: 1px solid var(--line); background: var(--bg-sunken); }
.now-card figcaption { color: var(--ink-dim); }

.prose.features { max-width: 64ch; }
.lab-cell__stack { color: var(--ink-dim); }

/* Garden framing: say plainly where each unfinished thing stands and what the
   next move is. More honest, and more interesting, than a card that just sits
   there being unfinished. */
.lab-cell { min-height: 17rem; }
/* Bottom-anchored with a fixed minimum, so the Now/Next blocks line up across
   cards even when one blurb or one next-step wraps to a different line count. */
.lab-cell__rows {
  margin-top: auto;
  min-height: 5.6rem;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  border-top: 1px solid var(--line);
  padding-top: 0.6rem;
  justify-content: flex-start;
}
.lab-cell__row { display: grid; grid-template-columns: 3.1rem minmax(0, 1fr); gap: 0.55rem; align-items: baseline; }
.lab-cell__k { color: var(--ink-dim); font-size: var(--step--2); letter-spacing: var(--tracking-mono); text-transform: uppercase; }
.lab-cell__v { color: var(--ink-2); font-size: var(--step--1); line-height: 1.5; }

/* ---------- cards ---------- */
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 360px), 1fr));
  gap: clamp(1.25rem, 3vw, 2.25rem) clamp(1rem, 2.4vw, 1.75rem);
}
.card { display: block; color: inherit; text-decoration: none; }
.card__media {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-1);
  background: var(--bg-sunken);
  aspect-ratio: 4 / 3;
  margin-bottom: var(--s-s);
  /* Hairline instead of a shadow: 16/16 designer sites and 17/17 developer
     sites in the research use borders, never elevation, for hierarchy. */
  box-shadow: inset 0 0 0 1px var(--line);
}
.card__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform var(--dur-5) var(--ease-out-quint), filter var(--dur-4) var(--ease-out-quint);
}
.card:hover .card__media img { transform: scale(1.045); }
.card__media--wide { aspect-ratio: 16 / 10; }
.card__media--square { aspect-ratio: 1 / 1; }
.card__media--tall { aspect-ratio: 3 / 4; }
.card__top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-s);
  margin-bottom: 0.35rem;
}
.card__title { font-size: var(--step-1); line-height: 1.25; letter-spacing: var(--tracking-tight); }
.card__desc { color: var(--ink-dim); font-size: var(--step--1); line-height: 1.55; max-width: 42ch; }
.card:hover .card__title { color: var(--accent); transition: color var(--dur-2) var(--ease-swift); }
.card--flat .card__media { box-shadow: none; }

/* ---------- tags / chips ---------- */
.tag {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent);
  border: 1px solid color-mix(in srgb, var(--accent) 34%, transparent);
  border-radius: var(--r-full);
  padding: 0.15rem 0.5rem;
  white-space: nowrap;
  vertical-align: middle;
}
.tag-list { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.chip {
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.05em;
  color: var(--ink-dim);
  border: 1px solid var(--line);
  border-radius: var(--r-full);
  padding: 0.2rem 0.65rem;
  white-space: nowrap;
}
.chip-list { display: flex; flex-wrap: wrap; gap: 0.4rem; }

/* ---------- lab grid ---------- */
.lab-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 290px), 1fr));
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--r-1);
  overflow: hidden;
}
.lab-cell {
  background: var(--bg);
  padding: var(--s-m);
  display: flex;
  flex-direction: column;
  gap: var(--s-s);
  min-height: 15rem;
  color: inherit;
  text-decoration: none;
  transition: background-color var(--dur-3) var(--ease-swift);
}
.lab-cell:hover { background: var(--bg-elev); }
.lab-cell__art { aspect-ratio: 1 / 1; overflow: hidden; border-radius: var(--r-1); background: var(--bg-sunken); box-shadow: inset 0 0 0 1px var(--line); }
.lab-cell__art img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--dur-5) var(--ease-out-quint); }
.lab-cell:hover .lab-cell__art img { transform: scale(1.06) rotate(-1deg); }
.lab-cell__foot { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-xs); }
.lab-cell__title { font-size: var(--step-0); letter-spacing: var(--tracking-tight); }

/* ---------- notes / writing list ---------- */
.notes { border-top: 1px solid var(--line); }
.note-row {
  display: grid;
  grid-template-columns: 7.5rem minmax(0, 1fr) auto;
  gap: var(--s-s) var(--s-m);
  align-items: baseline;
  padding-block: var(--s-s);
  border-bottom: 1px solid var(--line);
  color: inherit;
  text-decoration: none;
}
.note-row__date { font-family: var(--font-mono); font-size: var(--step--2); color: var(--ink-dim); font-variant-numeric: tabular-nums; }
.note-row__title { font-size: var(--step-0); line-height: 1.45; letter-spacing: var(--tracking-tight); transition: color var(--dur-2) var(--ease-swift); }
.note-row:hover .note-row__title { color: var(--accent); }
.note-row__arrow { color: var(--ink-dim); transition: transform var(--dur-3) var(--ease-out-quint), color var(--dur-2) var(--ease-swift); }
.note-row:hover .note-row__arrow { transform: translate(0.2em, -0.2em); color: var(--accent); }

/* ---------- about ---------- */
.about-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.6fr);
  gap: clamp(1.5rem, 5vw, 4.5rem);
  align-items: start;
}
.about-rail { position: sticky; top: calc(var(--header-h) + 2rem); display: flex; flex-direction: column; gap: var(--s-m); }
.portrait {
  aspect-ratio: 4 / 5;
  border-radius: var(--r-1);
  overflow: hidden;
  background: var(--bg-sunken);
  border: 1px solid var(--line);
}
.portrait img { width: 100%; height: 100%; object-fit: cover; }
.facts { display: flex; flex-direction: column; gap: 0.6rem; }
.facts__row { display: grid; grid-template-columns: 6rem minmax(0, 1fr); gap: var(--s-xs); align-items: baseline; }
.facts__key { font-family: var(--font-mono); font-size: var(--step--2); text-transform: uppercase; letter-spacing: var(--tracking-mono); color: var(--ink-dim); }
.facts__val { font-size: var(--step--1); color: var(--ink-2); }

/* Timeline */
.timeline { display: flex; flex-direction: column; }
.timeline__item {
  display: grid;
  grid-template-columns: 8.5rem minmax(0, 1fr);
  gap: var(--s-s) var(--s-m);
  padding-block: var(--s-s);
  border-bottom: 1px solid var(--line);
}
.timeline__when { font-family: var(--font-mono); font-size: var(--step--2); color: var(--ink-dim); font-variant-numeric: tabular-nums; padding-top: 0.35em; }
.timeline__what { font-size: var(--step-0); }
.timeline__role { color: var(--ink-dim); font-size: var(--step--1); }

/* ---------- pull quote ---------- */
.pullquote {
  font-family: var(--font-display);
  font-size: var(--step-3);
  line-height: 1.15;
  letter-spacing: var(--tracking-display);
  max-width: 30ch;
  padding-left: var(--s-m);
  border-left: 2px solid var(--accent);
}
.pullquote cite { display: block; margin-top: var(--s-s); font-family: var(--font-sans); font-style: normal; font-size: var(--step--1); color: var(--ink-dim); letter-spacing: 0; }

/* ---------- editorial prose (case studies) ---------- */
.prose { max-width: 68ch; }
.prose > * + * { margin-top: var(--s-s); }
.prose h2 {
  font-family: var(--font-display);
  font-size: var(--step-2);
  line-height: 1.2;
  letter-spacing: var(--tracking-display);
  margin-top: var(--s-xl);
}
.prose h3 { font-size: var(--step-1); margin-top: var(--s-l); }
.prose p { color: var(--ink-2); }
.prose strong { color: var(--ink); font-weight: 500; }
.prose em { font-family: var(--font-display); font-style: italic; font-size: 1.06em; }
.prose ul, .prose ol { padding-left: 1.15rem; color: var(--ink-2); }
.prose li + li { margin-top: 0.4rem; }
.prose ul li { list-style: none; position: relative; }
.prose ul li::before { content: ""; position: absolute; left: -1.05rem; top: 0.72em; width: 0.35em; height: 1px; background: var(--accent); }
.prose ol { list-style: decimal; }
.prose ol li::marker { font-family: var(--font-mono); font-size: 0.8em; color: var(--ink-dim); }
.prose blockquote { border-left: 2px solid var(--line-strong); padding-left: var(--s-m); font-family: var(--font-display); font-size: var(--step-1); color: var(--ink); }
.prose code {
  font-family: var(--font-mono);
  font-size: 0.85em;
  background: var(--bg-sunken);
  border: 1px solid var(--line);
  border-radius: var(--r-1);
  padding: 0.1em 0.35em;
}
.prose pre {
  background: var(--bg-sunken);
  border: 1px solid var(--line);
  border-radius: var(--r-2);
  padding: var(--s-s);
  overflow-x: auto;
  font-size: var(--step--1);
  line-height: 1.6;
}
.prose pre code { background: none; border: 0; padding: 0; font-size: 1em; }
.prose hr { border: 0; border-top: 1px solid var(--line); margin-block: var(--s-l); }
.prose a { color: var(--accent-ink); text-underline-offset: 3px; text-decoration-color: color-mix(in srgb, var(--accent) 40%, transparent); transition: text-decoration-color var(--dur-2) var(--ease-swift); }
.prose a:hover { text-decoration-color: var(--accent); }

/* Figures break out of the text column: full-bleed images are what make a
   case study feel like an editorial spread rather than a blog post. */
.figure { margin-block: var(--s-xl); max-width: none; }
.figure img { width: 100%; border-radius: var(--r-1); border: 1px solid var(--line); }
.figure figcaption {
  margin-top: 0.7rem;
  font-family: var(--font-mono);
  font-size: var(--step--2);
  color: var(--ink-dim);
  letter-spacing: 0.03em;
  display: flex;
  gap: 0.6em;
}
/* Full-bleed without a transform. The transform-based version broke because
   [data-reveal].is-in { transform: none } outranks a single class and silently
   cancelled the translateX(-50%), leaving the figure hanging off the right edge.
   Negative inline margins are immune to that. */
.figure--bleed {
  width: 100vw;
  max-width: 100vw;
  margin-inline: calc(50% - 50vw);
}
.figure--bleed img { border-radius: 0; border-inline: 0; }
/* The wipe starts once the image is in view; the img itself stays unclipped so
   the transition never fights the parallax-free layout. */
[data-reveal="clip"] > img { display: block; }

/* Meta table on case study pages */
.meta-table {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--s-s) var(--s-m);
  padding-block: var(--s-m);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  margin-block: var(--s-l);
}
.meta-table__key { font-family: var(--font-mono); font-size: var(--step--2); text-transform: uppercase; letter-spacing: var(--tracking-mono); color: var(--ink-dim); margin-bottom: 0.35rem; }
.meta-table__val { font-size: var(--step--1); color: var(--ink); }

/* Next-project pager */
.pager {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-m);
  padding-block: var(--s-l);
  border-top: 1px solid var(--line);
  text-decoration: none;
  color: inherit;
}
.pager__label { font-family: var(--font-mono); font-size: var(--step--2); letter-spacing: var(--tracking-mono); text-transform: uppercase; color: var(--ink-dim); margin-bottom: 0.4rem; }
.pager__title { font-family: var(--font-display); font-size: var(--step-3); line-height: 1.1; letter-spacing: var(--tracking-display); transition: color var(--dur-2) var(--ease-swift); }
.pager:hover .pager__title { color: var(--accent); }
.pager__arrow { font-size: var(--step-2); color: var(--ink-dim); transition: transform var(--dur-3) var(--ease-out-quint), color var(--dur-2) var(--ease-swift); }
.pager:hover .pager__arrow { transform: translateX(0.35rem); color: var(--accent); }

/* ---------- buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
  padding: 0.7rem 1.15rem;
  border-radius: var(--r-2);
  border: 1px solid var(--ink);
  background: var(--ink);
  color: var(--bg);
  font-family: var(--font-mono);
  font-size: var(--step--1);
  letter-spacing: 0.04em;
  text-decoration: none;
  transition: transform var(--dur-2) var(--ease-swift), opacity var(--dur-2) var(--ease-swift);
}
.btn:hover { opacity: .88; }
.btn:active { transform: scale(0.985); }
.btn--ghost { background: transparent; color: var(--ink); border-color: var(--line-strong); }
.btn--ghost:hover { background: var(--bg-elev); opacity: 1; border-color: var(--ink); }
.btn__arrow { transition: transform var(--dur-3) var(--ease-out-quint); }
.btn:hover .btn__arrow { transform: translateX(0.2em); }

/* ---------- splits & misc ---------- */
.split {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
  gap: clamp(1.5rem, 4vw, 3.5rem);
  align-items: start;
}
.stack { display: flex; flex-direction: column; }
.stack > * + * { margin-top: var(--s-s); }
.stack--l > * + * { margin-top: var(--s-l); }
.row { display: flex; align-items: center; gap: var(--s-s); flex-wrap: wrap; }
.mt-m { margin-top: var(--s-m); }
.mt-l { margin-top: var(--s-l); }

.capabilities {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 0.9rem;
  font-family: var(--font-mono);
  font-size: var(--step--1);
  color: var(--ink-dim);
  letter-spacing: 0.02em;
}
.capabilities li { display: flex; align-items: center; gap: 0.9rem; }
.capabilities li:not(:last-child)::after { content: ""; width: 3px; height: 3px; border-radius: 50%; background: var(--ink-faint); }

/* ---------- principles ----------
   Numbered statements set in the display serif. On a portfolio this is the
   section that actually sells the taste, so it gets the biggest type. */
.principles { display: flex; flex-direction: column; border-top: 1px solid var(--line); }
.principle {
  display: grid;
  grid-template-columns: 3rem minmax(0, 1fr);
  gap: var(--s-m);
  align-items: baseline;
  padding-block: clamp(0.85rem, 2vw, 1.25rem);
  border-bottom: 1px solid var(--line);
}
.principle__n { padding-top: 0.5em; }
.principle__text { line-height: 1.14; }
.principle .accent-serif, .principle__text em { font-style: italic; }

/* A prose list that is the list itself rather than nested inside .prose. */
ul.prose { padding-left: 1.15rem; }
ul.prose li { list-style: none; position: relative; color: var(--ink-2); }
ul.prose li::before {
  content: "";
  position: absolute;
  left: -1.05rem; top: 0.72em;
  width: 0.35em; height: 1px;
  background: var(--accent);
}
ul.prose li + li { margin-top: 0.45rem; }

/* A pending note is not interactive, so it must not look interactive. */
.note-row--pending { cursor: default; }
.note-row--pending .note-row__title { color: var(--ink-dim); }

/* ---------- statement ----------
   The only page on the site allowed to shout. One enormous sentence, then a
   narrow column that explains it. Used once on purpose: at this volume a second
   page would just be noise. */
.statement { padding-block: clamp(2.5rem, 11vh, 7rem) clamp(3rem, 8vh, 5rem); }
.statement__eyebrow { margin-bottom: var(--s-m); }
.statement__lines {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2.4rem, 1.1rem + 7.4vw, 8rem);
  line-height: 0.96;
  letter-spacing: -0.03em;
  margin: 0;
  max-width: 22ch;
}
.statement__lines span { display: block; }
.statement__punch {
  display: block;
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(1.5rem, 0.9rem + 2.6vw, 2.9rem);
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: var(--accent);
  margin-top: var(--s-m);
  max-width: 26ch;
}
.statement__body {
  max-width: 62ch;
  margin-top: clamp(2.5rem, 7vh, 4.5rem);
  display: flex;
  flex-direction: column;
  gap: var(--s-s);
}
.statement__body p { color: var(--ink-2); }
.statement__facts {
  margin-top: var(--s-xl);
  padding-top: var(--s-m);
  border-top: 1px solid var(--line);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: var(--s-m) var(--s-l);
}
.statement__fact { font-family: var(--font-mono); font-size: var(--step--1); color: var(--ink-dim); line-height: 1.5; }
.statement__actions { margin-top: var(--s-xl); display: flex; gap: var(--s-xs); flex-wrap: wrap; }

/* ---------- 404 ---------- */
.error-page {
  min-height: 68vh;
  display: grid;
  align-content: center;
  padding-block: var(--s-2xl);
}
/* The grid child is the .container, so the rhythm has to live on its
   children - a gap on .error-page itself would have nothing to space. */
.error-page .container { display: grid; justify-items: start; gap: var(--s-s); }
.error-page .container > .row { margin-top: var(--s-s); }
.error-page__code { font-family: var(--font-mono); font-size: var(--step--1); letter-spacing: 0.3em; color: var(--accent); }
.error-page__title { font-family: var(--font-display); font-size: var(--step-4); line-height: 1.02; letter-spacing: var(--tracking-display); max-width: 20ch; }

/* ---------- responsive ---------- */
@media (max-width: 860px) {
  .about-grid { grid-template-columns: minmax(0, 1fr); }
  .about-rail { position: static; }
  .portrait { max-width: 260px; }
  /* The dossier's third column is `auto` and its stack line is nowrap, so on a
     narrow screen it squeezed the title down to one word per line and ran over
     the meta. Below 860px the meta drops underneath and is allowed to wrap. */
  .dossier { grid-template-columns: 2.4rem minmax(0, 1fr); }
  .dossier__meta {
    grid-column: 2;
    align-items: flex-start;
    text-align: left;
    flex-direction: row;
    flex-wrap: wrap;
    gap: 0.45rem 0.9rem;
    padding-top: 0;
    white-space: normal;
  }
  .dossier__index { padding-top: 0.3em; }
  .log__item { grid-template-columns: minmax(0, 1fr); gap: 0.3rem; }
  .log__when { padding-top: 0; }
  .note-row { grid-template-columns: minmax(0, 1fr) auto; }
  .note-row__date { grid-column: 1 / -1; }
  .timeline__item { grid-template-columns: minmax(0, 1fr); gap: 0.3rem; }
  .timeline__when { padding-top: 0; }
}
/* Below 720px a single row cannot hold the wordmark, four nav links, the
   language toggle and the theme button. Research on top portfolios is explicit
   that they keep 2-6 visible text links rather than hiding navigation behind a
   burger, so the nav wraps onto its own row instead of collapsing. */
@media (max-width: 720px) {
  .header__inner {
    flex-wrap: wrap;
    gap: var(--s-2xs) var(--s-s);
    padding-block: 0.6rem 0.5rem;
    min-height: 0;
  }
  .wordmark { margin-right: 0; font-size: var(--step-0); }
  .header__tools { margin-left: auto; }
  .nav {
    order: 3;
    width: 100%;
    gap: clamp(0.85rem, 4.5vw, 1.5rem);
    padding-block: 0.55rem;
    border-top: 1px solid var(--line);
    overflow-x: auto;
    scrollbar-width: none;
  }
  .nav::-webkit-scrollbar { display: none; }
  .nav__link { padding-block: 0.15rem; }
}

@media (max-width: 560px) {
  .header__inner { gap: var(--s-xs); }
  .dossier__title { font-size: var(--step-1); }
  .hero__title { max-width: 100%; }
  .footer__grid { grid-template-columns: 1fr 1fr; }
}


/* ==========================================================================
   HOME · the loop  (added 2026-10-28)
   The homepage argues one thing: capture -> keep -> understand is a loop, not
   a pile. The ring is the only illustration on the page; everything else is
   type. Three strokes are drawn once on load, in reading order, so the eye
   learns the loop before it reads a single project name.
   ========================================================================== */
.loop { padding-block: clamp(3.5rem, 9vh, 7rem); border-top: 1px solid var(--line); }
.loop__grid { display: grid; grid-template-columns: minmax(0, 1.02fr) minmax(0, .98fr); gap: clamp(2rem, 5vw, 5rem); align-items: center; }
.loop__kicker { margin: 0 0 var(--s-s); }
.loop__title { font-family: var(--font-display); font-size: var(--step-3); line-height: var(--leading-snug); letter-spacing: var(--tracking-display); margin: 0 0 var(--s-m); font-weight: 400; }
.loop__title em { font-style: italic; color: var(--accent); }
.loop__deck { font-size: var(--step-0); line-height: var(--leading-body); color: var(--ink-2); max-width: var(--measure-narrow); margin: 0 0 var(--s-l); }
.loop__steps { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-s); }
.loop__step { display: grid; grid-template-columns: 3.2rem 1fr; gap: var(--s-s); align-items: baseline; padding-block: var(--s-s); border-top: 1px solid var(--line); }
.loop__step:last-child { border-bottom: 1px solid var(--line); }
.loop__step b { font-family: var(--font-display); font-style: italic; font-weight: 400; font-size: var(--step-1); color: var(--accent); }
.loop__step span { font-size: var(--step--1); color: var(--ink-2); line-height: 1.5; }
.loop__step span i { font-style: normal; color: var(--ink); font-weight: 600; }

.loop__ring { margin: 0; position: relative; width: 100%; max-width: 440px; aspect-ratio: 1 / 1; justify-self: center; }
.loop__ring svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.ring-arc { fill: none; stroke: var(--line-strong); stroke-width: 1.1; stroke-linecap: round; stroke-dasharray: 300; stroke-dashoffset: 300; animation: ring-draw 1.5s var(--ease-out-quint) forwards; }
.ring-arc:nth-of-type(1) { animation-delay: .2s; }
.ring-arc:nth-of-type(2) { animation-delay: .55s; }
.ring-arc:nth-of-type(3) { animation-delay: .9s; }
@keyframes ring-draw { to { stroke-dashoffset: 0; } }
.ring-dot { fill: var(--bg); stroke: var(--accent); stroke-width: 1.2; }
.loop__node { position: absolute; display: grid; gap: .1rem; text-decoration: none; padding: .5rem .7rem; border-radius: var(--r-3); transition: background var(--dur-2) var(--ease-swift); }
.loop__node b { font-family: var(--font-mono); font-size: 10px; letter-spacing: var(--tracking-mono); color: var(--accent); font-weight: 500; }
.loop__node span { font-size: var(--step--1); font-weight: 600; letter-spacing: var(--tracking-tight); color: var(--ink); white-space: nowrap; line-height: 1.2; }
.loop__node i { font-family: var(--font-mono); font-size: 9px; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-dim); font-style: normal; }
.loop__node:hover { background: var(--accent-soft); }
.loop__node:hover span { color: var(--accent-ink); }
.loop__node--a { left: 52.5%; top: 15%; transform: translate(-50%, -118%); }
.loop__node--b { left: 85%; top: 71.25%; transform: translate(-6%, -6%); }
.loop__node--c { left: 17.5%; top: 71.25%; transform: translate(-94%, -6%); }
.loop__core { position: absolute; left: 52.5%; top: 50%; transform: translate(-50%, -50%); text-align: center; font-family: var(--font-display); font-style: italic; font-size: var(--step-1); color: var(--ink-dim); line-height: 1.3; pointer-events: none; }

/* ---------- the three tools ---------- */
.three { padding-block: clamp(3.5rem, 9vh, 7rem); border-top: 1px solid var(--line); }
.three__head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-m); flex-wrap: wrap; margin-bottom: var(--s-xl); }
.three__title { font-family: var(--font-display); font-size: var(--step-3); font-weight: 400; letter-spacing: var(--tracking-display); margin: 0; line-height: 1.1; }
.tool { display: grid; grid-template-columns: 4.5rem minmax(0, 1fr) auto; gap: clamp(1rem, 2.6vw, 2.5rem); padding-block: clamp(1.6rem, 3.4vw, 2.6rem); border-top: 1px solid var(--line); align-items: start; position: relative; }
.tool:last-of-type { border-bottom: 1px solid var(--line); }
.tool__idx { font-family: var(--font-mono); font-size: var(--step--2); letter-spacing: var(--tracking-mono); color: var(--accent); padding-top: .5rem; }
.tool__verb { font-family: var(--font-display); font-style: italic; font-size: var(--step-1); color: var(--ink-dim); margin: 0 0 .35rem; }
.tool__name { font-size: var(--step-2); letter-spacing: var(--tracking-tight); margin: 0 0 .6rem; line-height: 1.1; }
.tool__note { font-size: var(--step-0); color: var(--ink-2); line-height: var(--leading-body); max-width: var(--measure); margin: 0 0 var(--s-s); }
.tool__facts { display: flex; flex-wrap: wrap; gap: .35rem .55rem; list-style: none; margin: 0; padding: 0; }
.tool__facts li { font-family: var(--font-mono); font-size: var(--step--2); letter-spacing: .02em; color: var(--ink-dim); border: 1px solid var(--line); border-radius: var(--r-full); padding: .28rem .6rem; }
.tool__go { font-family: var(--font-mono); font-size: var(--step--1); letter-spacing: .04em; color: var(--ink); text-decoration: none; border-bottom: 1px solid var(--line-strong); padding-bottom: 2px; white-space: nowrap; align-self: end; transition: color var(--dur-2) var(--ease-swift), border-color var(--dur-2) var(--ease-swift); }
.tool__go:hover { color: var(--accent); border-color: var(--accent); }
.tool__go span { color: var(--accent); }

/* ---------- also running ---------- */
.also { padding-block: clamp(3rem, 7vh, 5rem) clamp(3.5rem, 9vh, 7rem); border-top: 1px solid var(--line); }
.also__lead { margin: 0 0 var(--s-m); }
.also__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0; }
.also__item { display: grid; grid-template-columns: minmax(9rem, 15rem) minmax(0, 1fr); gap: var(--s-s) var(--s-m); align-items: baseline; padding-block: .9rem; border-top: 1px solid var(--line); }
.also__item:last-child { border-bottom: 1px solid var(--line); }
.also__name { font-size: var(--step-1); letter-spacing: var(--tracking-tight); }
.also__note { font-size: var(--step--1); color: var(--ink-2); line-height: 1.55; }
.also__coda { margin: var(--s-l) 0 0; font-family: var(--font-display); font-style: italic; font-size: var(--step-1); color: var(--ink-dim); max-width: var(--measure); line-height: 1.5; }

@media (max-width: 860px) {
  .loop__grid { grid-template-columns: 1fr; }
  .loop__ring { order: -1; max-width: 340px; margin-inline: auto; }
  .tool { grid-template-columns: 2.6rem minmax(0, 1fr); }
  .tool__go { grid-column: 2; justify-self: start; }
  .also__item { grid-template-columns: 1fr; gap: .3rem; }
}
@media (prefers-reduced-motion: reduce) {
  .ring-arc { animation: none; stroke-dashoffset: 0; }
}

/* ---------- hero with the loop beside it ---------- */
.hero__grid { display: grid; grid-template-columns: minmax(0, 1.32fr) minmax(0, .68fr); gap: clamp(1.5rem, 4vw, 4rem); align-items: center; }
.hero__main { min-width: 0; }
.hero__aside { position: relative; min-width: 0; }
.hero__aside .loop__ring { max-width: 420px; margin-left: auto; margin-right: 0; }

/* the spark: one accent dot travelling the loop, forever. It says "the loop
   keeps turning" without a caption. SMIL keeps it dependency-free. */
.ring-spark { fill: var(--accent); offset-rotate: 0deg; filter: drop-shadow(0 0 6px color-mix(in srgb, var(--accent) 55%, transparent)); }
.ring-track { stroke: none; fill: none; }

/* hover a node -> its arc lights up (the three arcs are in reading order) */
.loop__ring:has(.loop__node--a:hover) .ring-arc:nth-of-type(1),
.loop__ring:has(.loop__node--b:hover) .ring-arc:nth-of-type(2),
.loop__ring:has(.loop__node--c:hover) .ring-arc:nth-of-type(3) { stroke: var(--accent); stroke-width: 1.8; }

/* ---------- loop head + three-column steps ---------- */
.loop__head { display: grid; gap: var(--s-s); margin-bottom: var(--s-xl); }
.loop__steps--wide { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(1rem, 3vw, 2.5rem); }
.loop__steps--wide .loop__step { grid-template-columns: 1fr; gap: .5rem; border-top: 1px solid var(--line-strong); padding-top: var(--s-s); }
.loop__steps--wide .loop__step:last-child { border-bottom: 0; }
.loop__steps--wide .loop__step b { font-size: var(--step-2); }
.loop__steps--wide .loop__step span { font-size: var(--step--1); }

@media (max-width: 980px) {
  .hero__grid { grid-template-columns: 1fr; }
  .hero__aside { order: 2; }
  .hero__aside .loop__ring { max-width: 300px; margin-inline: auto; }
  .loop__steps--wide { grid-template-columns: 1fr; }
}

/* hero typography guard: at 78ch the CJK headline breaks inside a word unless
   we cap the display size and break the line by hand (the <br> lives in content). */
.hero__grid .hero__title { font-size: clamp(2.5rem, 1.1rem + 5.5vw, 6.75rem); line-height: 1.04; }
.hero__grid .hero__deck { max-width: 34ch; }
.hero__aside .loop__ring { max-width: 470px; }
.hero__aside .loop__node span { font-size: var(--step-0); }
.hero__aside .loop__core { font-size: var(--step-0); }
@media (max-width: 980px) {
  .hero__grid .hero__title { font-size: clamp(2.2rem, 1.2rem + 6vw, 3.4rem); }
}

/* balance: pull the ring closer to the words, keep CJK from breaking mid-phrase */
.hero__grid { grid-template-columns: minmax(0, 1.22fr) minmax(0, .78fr); gap: clamp(1rem, 2.6vw, 2.75rem); }
.hero__grid .hero__deck { max-width: 38ch; word-break: keep-all; overflow-wrap: break-word; }
.loop__deck { word-break: keep-all; }
.loop__node--b { top: 68.75%; }
.loop__node--c { top: 68.75%; }

/* three-tool rows: the action belongs to the name, not the page bottom */
.tool__go { align-self: start; margin-top: .35rem; }
.tool { transition: background var(--dur-2) var(--ease-swift); padding-inline: .6rem; margin-inline: -.6rem; }
.tool:hover { background: color-mix(in srgb, var(--ink) 3%, transparent); }
.tool__idx { transition: color var(--dur-2) var(--ease-swift), letter-spacing var(--dur-2) var(--ease-swift); }
.tool:hover .tool__idx { letter-spacing: .22em; }
.loop__steps--wide .loop__step span { font-size: var(--step-0); line-height: 1.6; }

/* ---------- pull quote ---------- */
.pull { padding-block: clamp(3rem, 8vh, 6rem); border-top: 1px solid var(--line); }
.pull__q { margin: 0; font-family: var(--font-display); font-weight: 400; font-size: var(--step-3); line-height: 1.24; letter-spacing: var(--tracking-display); color: var(--ink); max-width: 34ch; }
.pull__c { display: block; margin-top: var(--s-m); font-family: var(--font-mono); font-size: var(--step--2); letter-spacing: var(--tracking-mono); text-transform: uppercase; color: var(--ink-dim); font-style: normal; }
.pull__q em { color: var(--accent); font-style: italic; }
@media (max-width: 700px) { .pull__q { font-size: var(--step-2); } }

.pull__q { max-width: 40ch; }

/* ---------- mobile: single column, ring becomes a caption list ---------- */
@media (max-width: 980px) {
  .hero__grid { grid-template-columns: minmax(0, 1fr); }
  .hero__grid .hero__title { font-size: clamp(2rem, 8.2vw, 3rem); word-break: keep-all; }
  .hero__grid .hero__title br { display: none; }
  .hero__grid .hero__deck { max-width: 46ch; }
  .hero__aside { order: 2; }
  .hero__aside .loop__ring {
    max-width: min(320px, 84vw); margin-inline: auto;
    aspect-ratio: auto; display: flex; flex-direction: column; gap: .45rem;
  }
  .hero__aside .loop__ring svg { position: relative; inset: auto; width: 100%; height: auto; aspect-ratio: 1 / 1; }
  .hero__aside .loop__core { display: none; }
  .loop__node, .loop__node--a, .loop__node--b, .loop__node--c { position: static; transform: none; justify-items: center; padding: .3rem .5rem; }
  .loop__node span { font-size: var(--step-0); }
  .loop__node i { font-size: 9.5px; }
  .three__head { flex-direction: column; align-items: flex-start; gap: .5rem; }
  .tool { grid-template-columns: 2.4rem minmax(0, 1fr); }
  .tool__go { grid-column: 2 / -1; justify-self: start; margin-top: .2rem; }
  .pull__q { font-size: var(--step-2); word-break: keep-all; }
  .pull__q br { display: none; }
}
