/* micro·cc — marketing site
   Dark, Rams-restrained: one fixed accent, lowercase display type, hairline
   borders, no shadows, no gradients — with one deliberate exception, the
   sub-4% light on the cover (see header.intro). The palette is warmed a few
   points off neutral; both decisions come from the reference studies in
   ~/Desktop/study-0*.svg. */

:root {
  --bg: #121110;
  --bg-raised: #1e1c19;
  --ink: #f7f5f2;
  --muted: #9a958e;
  --muted-dim: #6b655e;
  --line: #221f1c;
  --line-strong: #2d2a26;
  --accent: #4a8a68; /* fixed — no JS writes to this */
  /* One flat 10px was doing every job. Both references scale radius with the
     size of the thing: mymind runs 44 on its big surface and 18 on the cards
     inside it. Bigger surface, bigger curve. */
  --r-panel: 22px;
  --r-media: 16px;
  --r-chip: 14px;
  --r-control: 10px;
  --r-micro: 4px;
  --display: 'Iowan Old Style', 'Palatino Linotype', Palatino, 'Book Antiqua', Georgia, serif;
  --sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
  --mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace;
}

* {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-weight: 300;
  font-size: 15px;
  line-height: 1.6;
  letter-spacing: -0.01em;
}

::selection {
  background: var(--accent);
  color: #121110;
}

a {
  color: inherit;
}

.wrap {
  max-width: 880px;
  margin: 0 auto;
  padding: 0 24px;
}

/* ---------- nav ---------- */

.nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 30;
  background: rgba(18, 17, 16, 0.86);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line);
  /* the copy up top is the introduction, not a masthead — the bar only
     arrives once you've scrolled past it. */
  transform: translateY(-100%);
  transition: transform 0.28s ease;
}
.nav.shown {
  transform: translateY(0);
}

.nav .wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 56px;
  max-width: none;
  padding: 0 30px;
}

/* the nav carries the same wordmark, at the same tiny scale as the corners */
.nav-mark {
  display: block;
  text-decoration: none;
  opacity: 0.62;
  transition: opacity 0.2s ease;
}
.nav-mark:hover { opacity: 1; }

.nav-links {
  display: flex;
  align-items: center;
  gap: 28px;
  font-family: var(--mono);
  font-size: 12.5px;
}

.nav-links a {
  text-decoration: none;
  color: var(--muted);
  transition: color 0.2s ease;
}

.nav-links a:hover,
.nav-links a.active {
  color: var(--ink);
}

.nav-links a.ext {
  color: var(--muted);
}

.banner-pre {
  font-family: var(--mono);
  font-variant-ligatures: none;
  font-feature-settings: "liga" 0, "calt" 0;
  white-space: pre;
  /* .hero sets text-align:center, which the <pre> inherits. On a 79-column
     art block that centres every SHORT line inside the widest line's box —
     the two top lines (19 spaces + "88") slide to the middle, so the dot
     lands over the wrong letter and the wordmark reads as garbage. The art
     is a fixed grid: it must be left-aligned. */
  text-align: left;
  /* Match the TUI's own metrics: 20px art at line-height 1.22. The art is a
     fixed 79-column grid, so it scales by font-size, never by wrapping. */
  line-height: 1.22;
  font-weight: 400;
  /* Body sets letter-spacing:-0.01em. On a 79-column monospace grid that
     accumulates ~8px of drift across the row and shears the letterforms —
     the TUI has no letter-spacing at all. Reset it to zero here. */
  letter-spacing: 0;
  /* 79 cols x 0.6em advance = 47.4 x font-size wide. This always fits the
     container (phone -> desktop) and is large on desktop, ~TUI scale. */
  font-size: min(7px, calc((100vw - 48px) / 47.4));
  display: block;
  margin: 0 0 22px;
  user-select: none;
  /* grey42 (#6c6c6c) is the shading stroke; accent is the letterform. Both
     values verified against the TUI's own Rich output. */
  color: #6c6c6c;
}

.banner-pre--nav {
  font-size: min(5px, calc((100vw - 48px) / 47.4));
  line-height: 1.16;
  margin: 0;
}

.banner-pre .a {
  color: var(--accent);
}

h1.headline {
  font-weight: 200;
  text-transform: lowercase;
  font-size: clamp(2rem, 4.4vw, 3.1rem);
  line-height: 1.15;
  letter-spacing: 0.005em;
  margin: 0 0 20px;
  max-width: 720px;
  margin-left: auto;
  margin-right: auto;
}

.sub {
  color: var(--muted);
  max-width: 560px;
  margin: 0 auto 40px;
  font-size: 15px;
  line-height: 1.65;
}



.install {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  font-family: var(--mono);
  font-size: 13px;
  color: var(--ink);
  /* no frame -- mymind's content floats. It is held apart by the surface step
     instead, which is why --bg-raised moved away from --bg in this commit. */
  background: var(--bg-raised);
  border-radius: var(--r-chip);
  padding: 12px 16px;
}

.install .prompt {
  color: var(--muted-dim);
}

.install button {
  background: none;
  border: none;
  color: var(--muted);
  cursor: pointer;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 0;
  transition: color 0.2s ease;
}

.install button:hover {
  color: var(--ink);
}

kbd {
  color: var(--ink);
  font-family: var(--mono);
  border: none;
  background: none;
  padding: 0;
}

.eyebrow {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted-dim);
  margin: 0 0 14px;
}

h2.title {
  /* the serif used to live only in the hero statement. Bringing it down to
     every section heading splits the page into three clear voices:
     serif display (headings) / mono (labels) / sans (body). */
  font-family: var(--display);
  font-style: italic;
  font-weight: 400;
  text-transform: lowercase;
  /* serif reads smaller than the sans at the same size, and wants the hero's
     tighter tracking rather than the sans's 0.005em */
  font-size: clamp(1.6rem, 2.8vw, 2.15rem);
  letter-spacing: -0.012em;
  margin: 0 0 18px;
}

p.body-text {
  color: var(--muted);
  max-width: 620px;
  margin: 0 0 16px;
  font-size: 14.5px;
}

p.body-text:last-child {
  margin-bottom: 0;
}

p.body-text strong {
  color: var(--ink);
  font-weight: 500;
}

code.inline {
  font-family: var(--mono);
  font-size: 0.92em;
  color: var(--ink);
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: var(--r-micro);
  padding: 1px 6px;
  /* a long path in inline code was pushing the 360px viewport 6px wide */
  overflow-wrap: anywhere;
}




/* ---------- footer ---------- */

/* ---------- footer ----------
   The wordmark, a slow drift of characters rising from the bottom, and the
   links. The field is generated in script.js and duplicated so the loop has
   no seam. */

.site-footer {
  border-top: 1px solid var(--line);
  padding: 72px 0 56px;
}

.f-wrap {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 48px;
}

.f-left { min-width: 0; }

.f-banner {
  font-size: min(5px, calc((100vw - 48px) / 47.4));
  margin: 0 0 20px;
}

/* Phones: the wordmark is a fixed 79-column grid, so it can only shrink by
   font-size, never by wrapping. Cover, nav and footer land on one size. */
@media (max-width: 640px) {
  .f-banner { font-size: min(2.2px, calc((100vw - 36px) / 47.4)); }
}

.f-row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 22px;
  font-family: var(--mono);
  font-size: 12px;
}

.f-row a {
  text-decoration: none;
  color: var(--muted);
  transition: color 0.2s ease;
}

.f-row a:hover { color: var(--ink); }

.f-note { color: var(--muted-dim); }

/* ---------- the old terminal ----------
   A little phosphor CRT parked in the corner: green on near-black, scanlines,
   a soft bloom, and one blinking block cursor. */

.crt {
  position: relative;
  flex-shrink: 0;
  width: 296px;
  padding: 16px 18px;
  border-radius: var(--r-panel);
  background: radial-gradient(120% 130% at 50% 30%, #08130c 0%, #040805 100%);
  border: 1px solid #12301f;
  overflow: hidden;
  box-shadow: inset 0 0 46px rgba(72, 255, 148, 0.06);
}

/* scanlines */
.crt::before {
  content: "";
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0) 0 2px,
    rgba(0, 0, 0, 0.34) 2px 3px
  );
  pointer-events: none;
}

/* vignette */
.crt::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(115% 105% at 50% 50%, rgba(0, 0, 0, 0) 52%, rgba(0, 0, 0, 0.62) 100%);
  pointer-events: none;
}

.crt-text {
  position: relative;
  z-index: 1;
  margin: 0;
  font-family: var(--mono);
  font-size: 11.5px;
  line-height: 1.55;
  white-space: pre;
  color: #58e08e;
  text-shadow: 0 0 7px rgba(88, 224, 142, 0.5);
}

.crt-cursor {
  animation: blink 1.05s steps(1) infinite;
}

@keyframes blink {
  0%, 50% { opacity: 1; }
  50%, 100% { opacity: 0; }
}

@media (max-width: 820px) {
  .f-wrap {
    flex-direction: column;
    align-items: flex-start;
    gap: 32px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .crt-cursor { animation: none; }
}

/* ---------- docs ---------- */

.docs {
  display: grid;
  grid-template-columns: 180px 1fr;
  gap: 56px;
  align-items: start;
  padding-top: 56px;
  padding-bottom: 96px;
  max-width: 1020px;
}

.toc {
  position: sticky;
  top: 80px;
  display: flex;
  flex-direction: column;
  gap: 9px;
}

.toc .eyebrow {
  margin: 0 0 6px;
}

.toc a {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--muted);
  text-decoration: none;
  transition: color 0.2s ease;
}

.toc a:hover {
  color: var(--ink);
}

.doc-body {
  min-width: 0;
}

.doc-body > section {
  padding-bottom: 52px;
  margin-bottom: 52px;
  border-bottom: 1px solid var(--line);
}

.doc-body > section:last-child {
  border-bottom: none;
  margin-bottom: 0;
  padding-bottom: 0;
}

.doc-body .headline {
  max-width: none;
  margin-left: 0;
  margin-right: 0;
}

.doc-body .sub {
  margin-left: 0;
  margin-right: 0;
  max-width: 640px;
}

.doc-body h2.title {
  margin-bottom: 16px;
}

/* code block */

pre.code {
  font-family: var(--mono);
  font-size: 12.5px;
  color: var(--ink);
  margin: 0 0 20px;
  padding: 0;
  background: none;
  border: none;
  line-height: 1.75;
  white-space: pre;
  overflow-x: auto;
}

/* ---------- self-modification: numbered flow + terminal frame ---------- */

/* diff / accent tints inside the frame */


p.src {
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--muted-dim);
  margin: 20px 0 0;
}

p.src a {
  color: var(--muted);
  text-decoration: none;
  border-bottom: 1px solid var(--line-strong);
  transition: color 0.2s ease, border-color 0.2s ease;
}

p.src a:hover {
  color: var(--ink);
  border-color: var(--line-strong);
}

/* ---------- responsive ---------- */

@media (max-width: 720px) {
  .docs {
    grid-template-columns: 1fr;
    gap: 32px;
    padding-top: 36px;
  }
  .toc {
    position: static;
    flex-direction: row;
    flex-wrap: wrap;
    gap: 14px;
    padding-bottom: 20px;
    border-bottom: 1px solid var(--line);
  }
  .toc .eyebrow {
    width: 100%;
    margin-bottom: 0;
  }
}

/* Phones: keep the wordmark, just scale it. It is a fixed 79-column grid, so
   it can only give way by font-size, never by wrapping — and the three links
   have to hold one line (unwrapped they are ~190px). The subtraction below is
   exactly that links block plus the two gutters; whatever is left is the
   mark's to use. The alternative the first pass took — swapping the ASCII for
   a text mark — read as "you removed our banner", so it does not.
   ORDER MATTERS: this must stay after `.banner-pre { display: block }` and the
   720px block above. Same specificity, so whichever comes last wins — and
   that is exactly how the wordmark silently stayed 143px wide the first time. */
@media (max-width: 720px) {
  .nav .wrap { padding: 0 16px; }
  .banner-pre--nav { font-size: min(2.2px, calc((100vw - 252px) / 47.4)); }
  .nav-links { gap: 12px; font-size: 11px; }
  .nav-links a { white-space: nowrap; }
}

/* ---------- cover (home) ----------
   Full height, one centred statement, a tiny mark in the corner. A title
   page, not a masthead and not a narrow column. Background is deliberately
   plain for now — the texture gets decided separately. */

header.intro {
  position: relative;
  /* mymind's cover is LIT -- a soft light source off-centre, not a flat fill.
     This is a single radial held at 3.8%, deliberately under the threshold
     where the eye reads "a gradient". It is the one exception to the no-
     gradients rule at the top of this file, and it is on the background layer
     so it never sits over the type. */
  background: radial-gradient(74% 58% at 50% 34%,
                              rgba(255, 255, 255, 0.038) 0%,
                              rgba(255, 255, 255, 0) 70%);
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 120px 24px;
}

.intro-mark {
  position: absolute;
  top: 30px;
  left: 30px;
  text-decoration: none;
  /* mymind's rule: the wordmark is the faintest thing on the surface. .5 read
     as a logo competing with the statement; .38 sits back and lets the
     statement hold the page. Hover still brings it up. */
  opacity: 0.38;
  transition: opacity 0.2s ease;
}

.intro-mark:hover { opacity: 0.95; }

.banner-pre--mark {
  font-size: min(5px, calc((100vw - 48px) / 47.4));
  margin: 0;
}

.intro-center {
  max-width: 780px;
  /* As a flex item this defaults to min-width:auto — it refuses to shrink
     below its content. The install command is one unbreakable ~500px URL, so
     this box was forced to 733px and centred in a 390px viewport: the whole
     hero got sliced off on BOTH sides. Pin it to the container instead. */
  width: 100%;
  min-width: 0;
  text-align: center;
}

.intro-statement {
  font-weight: 200;
  font-size: clamp(1.8rem, 3.8vw, 3rem);
  line-height: 1.22;
  letter-spacing: -0.015em;
  margin: 0 0 40px;
}

@media (max-width: 900px) {
  header.intro { min-height: 86vh; padding: 96px 24px; }
  .intro-mark { top: 18px; left: 18px; }
}

/* ---------- feature panels (home) ----------
   Media and copy side by side, nothing boxed: no card, no border, no frame.
   The SVG carries its own ground; the page just gives it room. */

section.feature {
  padding: 92px 0;
}

.feature-inner {
  max-width: 1120px;
  margin: 0 auto;
  padding: 0 24px;
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
  gap: 56px;
  align-items: center;
}

.feature-media img,
.feature-media video {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--r-media);
}

/* the self-change clip is a portrait screen recording — give it a narrower
   column so it doesn't tower over its copy */
.feature-inner--tall {
  grid-template-columns: minmax(0, 0.72fr) minmax(0, 1fr);
  align-items: center;
}
@media (max-width: 900px) {
  .feature-inner--tall { grid-template-columns: 1fr; }
}

.feature-copy p.body-text {
  max-width: 46ch;
}

/* closing write-up */
section.closing {
  padding: 96px 0 120px;
}

section.closing p.body-text {
  max-width: 68ch;
}

section.closing .install {
  margin-top: 30px;
}

@media (max-width: 900px) {
  section.feature { padding: 64px 0; }
  .feature-inner {
    grid-template-columns: 1fr;
    gap: 30px;
  }
  section.closing { padding: 64px 0 84px; }
}

/* ---------- docs: term lists ----------
   A command or tool, and what it does. Two columns, no rules, no boxes. */

.terms {
  display: grid;
  grid-template-columns: minmax(0, 190px) minmax(0, 1fr);
  gap: 10px 28px;
  margin: 26px 0 24px;
}

.terms dt {
  font-family: var(--mono);
  font-size: 12.5px;
  color: var(--ink);
}

.terms dd {
  margin: 0;
  color: var(--muted);
  font-size: 13.5px;
  line-height: 1.55;
}

@media (max-width: 720px) {
  .terms {
    grid-template-columns: 1fr;
    gap: 4px 0;
  }
  .terms dd {
    margin: 0 0 12px;
  }
}

/* which docs page you are on */
.toc a.on {
  color: var(--ink);
}

/* ---------- closing: the loop ---------- */

.loop-pair {
  max-width: 1120px;
  margin: 0 auto;
  padding: 0 24px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 400px;
  gap: 72px;
  align-items: center;
}
.loop-copy p.body-text { max-width: 52ch; }
.loop-svg { width: 100%; height: auto; display: block; overflow: visible; }
.loop-svg .l-lab { font-family: var(--mono); font-size: 13px; letter-spacing: .14em; text-transform: uppercase; fill: #777; }
.loop-svg .l-cap { font-family: var(--mono); font-size: 15px; fill: #aaa; }
.loop-svg .l-small { font-family: var(--mono); font-size: 12px; letter-spacing: .1em; fill: #666; }
/* the centre readout: what is happening to the file right now. Sits after
   .l-small so .l-acc / .l-warn can still win the fill. */
.loop-svg .l-stat { font-family: var(--mono); font-size: 12.5px; letter-spacing: .02em; fill: #9c9c9c; }
.loop-svg .l-sub { font-size: 11px; letter-spacing: .06em; fill: #6f6f6f; }
.loop-svg .l-acc { fill: #a8d5ba; }
/* the motion-off stand-in for the narration; see the media query below */
.loop-svg .l-static { display: none; }
.loop-svg .l-warn { fill: #e0a39a; }
@media (max-width: 900px) {
  .loop-pair { grid-template-columns: 1fr; gap: 40px; }
  .loop-svg { max-width: 400px; margin: 0 auto; }
}
@media (prefers-reduced-motion: reduce) {
  .loop-svg .pulse { display: none; }
  /* every .l-stat is SMIL-raised from opacity 0, so with motion off they are all
     invisible; show one representative beat rather than an empty centre. */
  .loop-svg .l-stat { display: none; }
  .loop-svg .l-static { display: inline; }
}

/* ---------- docs additions ---------- */

.tag {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted-dim);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-micro);
  padding: 1px 6px;
  margin-left: 6px;
  white-space: nowrap;
}

.paths { display: grid; gap: 0; margin-top: 8px; }
.paths a {
  display: grid;
  grid-template-columns: minmax(0, 150px) minmax(0, 1fr);
  gap: 24px;
  padding: 18px 0;
  border-top: 1px solid var(--line);
  text-decoration: none;
  transition: background 0.2s ease;
}
.paths a:last-child { border-bottom: 1px solid var(--line); }
.paths .k { font-family: var(--mono); font-size: 12.5px; color: var(--ink); }
.paths .v { color: var(--muted); font-size: 13.5px; }

figure.loop-fig { margin: 8px 0 30px; max-width: 420px; }
figure.loop-fig .loop-svg { width: 100%; height: auto; }

.toc a.toc-sub { padding-left: 12px; font-size: 11.5px; color: var(--muted-dim); }
.toc a.toc-sub.on { color: var(--accent); }
.search-open {
  margin-top: 14px;
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--muted-dim);
  background: none;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-control);
  padding: 6px 10px;
  cursor: pointer;
  text-align: left;
  transition: color 0.2s ease, border-color 0.2s ease;
}
.search-open:hover { color: var(--ink); border-color: var(--line-strong); }

.pager {
  display: flex;
  justify-content: space-between;
  margin: 56px 0 0;
  padding-top: 24px;
  border-top: 1px solid var(--line);
  font-family: var(--mono);
  font-size: 12px;
}
.pager a { color: var(--muted); text-decoration: none; transition: color 0.2s ease; }
.pager a:hover { color: var(--ink); }
.built { font-family: var(--mono); font-size: 11px; color: var(--muted-dim); margin: 18px 0 0; }
.built a { color: var(--muted); text-decoration: none; border-bottom: 1px solid var(--line-strong); }

pre.code { position: relative; padding: 14px 16px; background: var(--bg-raised); border-radius: var(--r-panel); }
.code-copy {
  position: absolute;
  top: 8px;
  right: 10px;
  background: none;
  border: none;
  color: var(--muted-dim);
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.2s ease, color 0.2s ease;
}
pre.code:hover .code-copy { opacity: 1; }
.code-copy:hover { color: var(--ink); }

.pal {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: rgba(18, 17, 16, 0.72);
  backdrop-filter: blur(4px);
  display: flex;
  justify-content: center;
  align-items: flex-start;
  padding-top: 14vh;
}
.pal-box {
  width: min(560px, calc(100vw - 32px));
  background: var(--bg-raised);
  border-radius: var(--r-panel);
  overflow: hidden;
}
.pal-input {
  width: 100%;
  background: none;
  border: none;
  outline: none;
  color: var(--ink);
  font-family: var(--mono);
  font-size: 14px;
  padding: 16px 18px;
}
.pal-list { border-top: 1px solid var(--line); }
.pal-list:empty { display: none; }
.pal-row {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding: 10px 18px;
  text-decoration: none;
  font-family: var(--mono);
  font-size: 12.5px;
  color: var(--muted);
}
.pal-row.on { background: var(--bg); color: var(--ink); }
.pal-row .p { color: var(--muted-dim); font-size: 11px; }

.nf { min-height: 100vh; display: flex; flex-direction: column; justify-content: center; max-width: 880px; margin: 0 auto; padding: 0 24px; }
.nf-links { display: flex; gap: 22px; font-family: var(--mono); font-size: 12px; margin-top: 8px; }
.nf-links a { color: var(--muted); text-decoration: none; }
.nf-links a:hover { color: var(--ink); }

@media (max-width: 720px) {
  .paths a { grid-template-columns: 1fr; gap: 4px; }
  .search-open { display: none; }
}
.nf .headline, .nf .sub { margin-left: 0; margin-right: 0; max-width: none; }

/* ---------- cover: typography ----------
   An italic serif statement, mono-caps microlabels in the corners, and a
   faint film grain. The statement's last two words link to the loop diagram. */

header.intro::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0.028;
  background-image: url("assets/grain.png");
  background-size: 128px 128px;
}

.intro-center { position: relative; }

.intro-statement {
  font-family: var(--display);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(2rem, 4.4vw, 3.4rem);
  line-height: 1.18;
  letter-spacing: -0.012em;
  text-wrap: balance;
}

.intro-statement a {
  white-space: nowrap;
  text-decoration: underline dotted;
  text-decoration-color: var(--accent);
  text-decoration-thickness: 1.5px;
  text-underline-offset: 0.18em;
  transition: color 0.2s ease;
}
.intro-statement a:hover { text-decoration-color: var(--ink); }

.intro-labels .il {
  position: absolute;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted-dim);
  text-decoration: none;
  transition: color 0.2s ease;
}
.intro-labels a.il:hover { color: var(--ink); }
.il--tr  { top: 32px; right: 128px; }
.il--tr2 { top: 32px; right: 30px; }
.il--bl  { bottom: 30px; left: 30px; }
.il--br  { bottom: 30px; right: 30px; }

section.closing { scroll-margin-top: 72px; }

@media (max-width: 900px) {
  .il--tr  { top: 20px; right: 108px; }
  .il--tr2 { top: 20px; right: 18px; }
  .il--bl  { bottom: 18px; left: 18px; }
  .il--br  { display: none; }
}

/* Phones: the corner wordmark stays, a notch smaller. What could not stay is
   the pair of microlabels pinned opposite it — the mark is a fixed 79-column
   grid (~190px here) and the labels left it nowhere to sit (83px of overlap at
   390). Both labels are duplicates of the nav links, so they are the ones that
   step aside.
   Placed after the .il--* rules above: same specificity, source order decides. */
@media (max-width: 640px) {
  .banner-pre--mark { font-size: min(2.2px, calc((100vw - 36px) / 47.4)); }
  .il--tr, .il--tr2 { display: none; }
}

/* ---------- cover: install switch ---------- */

[hidden] { display: none !important; }

.install-tabs { display: none; justify-content: center; gap: 22px; margin: 0 0 14px; }
.js .install-tabs { display: flex; }
.install-tabs button {
  background: none;
  border: none;
  border-bottom: 1px solid transparent;
  padding: 0 0 4px;
  cursor: pointer;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted-dim);
  transition: color 0.2s ease, border-color 0.2s ease;
}
.install-tabs button:hover { color: var(--ink); }
.install-tabs button.on { color: var(--ink); border-bottom-color: var(--accent); }

.install-note { font-family: var(--mono); font-size: 11.5px; color: var(--muted-dim); margin: 14px 0 0; }
.install-note code { color: var(--muted); }

@media (max-width: 720px) {
  /* The command is one long token — a 64-char URL. The old rule here set
     `overflow-x: auto` on the span, which is inert: overflow is ignored on
     inline boxes. So the chip stayed as wide as the URL and pushed the page
     sideways. Give the span a real flex box and let it break mid-URL.
     `overflow-wrap: anywhere` (unlike `break-word`) also lowers the item's
     min-content width — that is what actually permits the shrink. */
  .install {
    display: flex;
    flex-wrap: nowrap;
    align-items: flex-start;
    width: 100%;
    max-width: 100%;
    min-width: 0;
    gap: 10px;
    padding: 12px 14px;
    font-size: 12px;
    text-align: left;
  }
  .install span:nth-child(2) {
    flex: 1 1 auto;
    min-width: 0;
    white-space: normal;
    overflow-wrap: anywhere;
    line-height: 1.5;
  }
  .install .prompt,
  .install button { flex: 0 0 auto; }
  .install-tabs { flex-wrap: wrap; gap: 14px 18px; }
}

/* ---------- density as texture ----------
   The poster's dot matrix, with our data: one mark per module file, area set by
   real line count, value the only variable. No hue -- the accent stays free for
   state. */
.texture { margin: 30px 0 26px; }
.texture svg { width: 100%; height: auto; display: block; color: var(--ink); }

/* A mark is a few pixels wide, so the full 30px cell is the hover target (the
   build.py side puts a transparent hit rect under each one). Hovering anywhere
   in the cell takes the mark to full value, immediately -- the native tooltip
   still carries the path and line count, but the response no longer waits on it. */
.texture .cell circle { transition: fill-opacity 0.12s ease; }
.texture .cell:hover circle { fill-opacity: 1; }
.texture .cell:hover { cursor: default; }

/* The texture's own label. A fixed-position div rather than a title attribute,
   so it appears immediately and can be styled; positioned from the pointer and
   flipped near the viewport edges. */
.tip {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 80;
  pointer-events: none;
  white-space: nowrap;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.01em;
  color: var(--ink);
  background: var(--bg-raised);
  border-radius: var(--r-control);
  padding: 6px 9px;
  opacity: 0;
  transition: opacity 0.1s ease;
}
.tip.on { opacity: 1; }

/* The texture is a wide, label-dense figure, and it scales as ONE unit -- so a
   phone would shrink its 11.5px mono row labels to about 4px, which is worse
   than not showing them. Let it keep a readable width and scroll inside its own
   box instead; the page itself still never scrolls sideways. */
@media (max-width: 720px) {
  .texture { overflow-x: auto; }
  .texture svg { width: 660px; }
}
