/* Lab (It. 52) - side projects, in the open. Loads after main.css; only what
   this page needs. Same grammar as the legal chapter and the focus index:
   editorial rows with hairlines, NO cards. A card grid holding one item reads
   as broken; a numbered row reads as the start of an index - which is the
   honest shape for a collection that is genuinely just beginning.
   Underlined link reuses the shared quiet-link group in main.css (house rule
   §4: a new underlined link JOINS that group, it does not invent a style). */

.lab-open {
  padding-top: clamp(10rem, 24vh, 15rem);
  padding-bottom: clamp(3.5rem, 8vh, 5.5rem);
}
.lab-title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(2.4rem, 5.4vw, 4.6rem);
  letter-spacing: -0.026em;
  line-height: 1.02;
  text-wrap: balance; /* house rule: display lines balance, never pretty */
  max-width: 16ch;
}
.lab-intro {
  margin-top: clamp(1.6rem, 3vw, 2.4rem);
  color: var(--ink-dim);
  max-width: 34em;
  font-size: 1.08rem;
  line-height: 1.7;
}

/* ---- The index ---- */
.lab-body { padding-top: 0; }
.lab-list { border-top: 1px solid var(--line); }
.lab-item {
  display: grid;
  grid-template-columns: 3.25rem 1fr;
  gap: clamp(1.25rem, 4vw, 3rem);
  padding-block: clamp(2.6rem, 6vh, 4rem);
  border-bottom: 1px solid var(--line);
}
.lab-num {
  font-size: 0.76rem;
  font-weight: 500;
  letter-spacing: 0.2em;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
  transition: color 0.5s ease;
}
.lab-name {
  font-family: var(--font-display);
  font-weight: 620;
  font-size: clamp(1.45rem, 3.2vw, 2.5rem);
  letter-spacing: -0.022em;
  line-height: 1.06;
  color: var(--ink);
  text-wrap: balance;
}
.lab-line {
  margin-top: 0.85rem;
  color: var(--ink-dim);
  max-width: 52ch;
  font-size: 1.02rem;
  line-height: 1.65;
}
/* Facts, not badges: platform, language, licence. No star counts - a number
   that can embarrass you on a quiet week is not proof of anything. */
.lab-meta {
  margin-top: 1.15rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.55rem 0.9rem;
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  color: var(--ink-faint);
}
.lab-meta span + span::before {
  content: "·";
  margin-right: 0.9rem;
  color: var(--line);
}
/* Scramble arrival (It. 53, same grammar as the constellation hub and the
   stack ticker - glyphs cycle, then lock left to right).
   The ember is the ARRIVAL, not the resting state: unlike the hub, which is
   the one centrepiece and stays lit, four permanently accent labels would
   compete with it and shout. So they heat up as they land and cool to their
   quiet ink-faint a beat later. Widths are locked in JS so cycling glyphs
   never jitter the line. */
.lab-meta span.is-scrambling { color: var(--accent); }
.lab-meta span.is-landed {
  color: var(--accent);
  animation: lab-cool 1.5s ease 0.45s forwards;
}
@keyframes lab-cool { to { color: var(--ink-faint); } }
/* Before the scramble runs, the labels wait invisible - otherwise the real
   text would flash for one frame before being replaced by glyphs. */
/* PRIMI POTOMCI (> span), nikdy jen `span`: kazdy stitek je rozsekany na
   znakove spany .m-ch, takze potomkovy selektor schoval i JE - a vyjimka
   zvedala opacity jen u rodicu s .is-landed. Vysledek: rodic svitil, znaky
   zustaly neviditelne a stitky nebyly videt vubec (It. 55). */
.lab-meta > span { display: inline-block; text-align: left; }
.js .lab-meta.will-scramble > span { opacity: 0; }
.js .lab-meta.will-scramble > span.is-scrambling,
.js .lab-meta.will-scramble > span.is-landed { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .lab-meta span.is-landed { animation: none; color: var(--ink-faint); }
}
.lab-link { display: inline-flex; align-items: center; gap: 0.5rem; margin-top: 1.5rem; color: var(--ink-dim); }
.lab-link svg { width: 12px; height: 12px; }

/* ---- Preview ----
   Framed, deliberately NOT full-bleed: measured 17.7.2026, the screenshot's
   darkest tone is #1e1c25 (cool, violet-leaning) while --bg is #0d0c0b (warm).
   Close in luminance, different in temperature - bleeding it into the page
   would show that seam. A hairline frame reads as "a screen", and the seam
   becomes a border instead of a mistake. (Same reasoning as .ql-plate, It.38.) */
/* Not full width: measured 20.7.2026 the shot ran 1156px against a 439px text
   column (ratio 0.38) and the two read as unrelated objects. 74% is the offset
   the case-study galleries already use (.ox-g-*), and it ties the image to the
   text instead of dwarfing it. */
.lab-shot {
  max-width: 74%;
  margin-top: clamp(1.8rem, 4vh, 2.6rem);
  border: 1px solid var(--line);
  border-radius: 3px;
  overflow: hidden;
  background: #17161e; /* the screenshot's own dark, so letterboxing never flashes */
  line-height: 0;
}
.lab-shot img { width: 100%; height: auto; display: block; }

@media (hover: hover) {
  .lab-item:hover .lab-num { color: var(--accent); }
}

@media (max-width: 640px) {
  .lab-item { grid-template-columns: 1fr; gap: 0.75rem; }
  .lab-shot { max-width: 100%; }
  .lab-num { letter-spacing: 0.24em; }
}

/* Return home. Same three rules as .legal-return in legal.css, copied rather
   than imported: pulling a whole stylesheet in for three lines would make
   this page depend on the legal chapter for no reason. */
/* Shorter than the legal chapter's closing beat (7-11rem): those pages carry
   long prose, so the void reads as a breath. A one-item index is short - the
   same gap measured 337px and read as an unfinished page, not restraint. */
.lab-return { text-align: center; padding-block: clamp(4rem, 9vh, 6rem); }
.lab-back { flex-direction: row; }
.lab-back svg { rotate: 90deg; }
.lab-foot {
  margin-top: 2.2rem;
  font-size: 0.78rem;
  color: var(--ink-faint);
}
.lab-foot a { color: inherit; transition: color 0.4s ease; }
.lab-foot a:hover { color: var(--ink-dim); }
