/* lab.briaan.com — shared frame. Every lab page links this first.
   The frame never moves: breadcrumbs top-left, caption bottom-left,
   reset top-right. Pages supply the chaos in between.
   Defaults: #fff ground, Fragment Mono 13px, hierarchy by muting
   (#999), 1px PURE WHITE (#fff) borders ONLY on media that overlaps
   other media — never grey.

   Type (2026-07-23, Brian): Fragment Mono replaced Courier Prime Sans
   everywhere. Bitcount Prop Single is the display face — used ONLY for
   the lab directory's titles, never for body copy. Both self-hosted
   under /fonts/ (OFL, licenses beside the files); no Google Fonts CDN,
   per the design-taste rule. */

@font-face {
  font-family: 'Fragment Mono';
  src: url('/fonts/FragmentMono-Regular.ttf') format('truetype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Fragment Mono';
  src: url('/fonts/FragmentMono-Italic.ttf') format('truetype');
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}

/* Bitcount Prop Single, variable. Axes are CRSV, ELSH, ELXP, slnt and
   wght — there is NO wdth axis, and no axis moves the advance width
   (measured: identical at every setting). ELXP ("element expansion",
   0–100) stretches each pixel-dot into a bar and is the font's real
   widening axis; wght grows the dots. Those two are what the directory
   animates. */
@font-face {
  font-family: 'Bitcount Prop Single';
  src: url('/fonts/BitcountPropSingle.ttf') format('truetype');
  font-weight: 100 900;
  font-display: swap;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

body {
  background: #fff;
  color: #111;
  font-family: 'Fragment Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
  font-size: 13px;
  line-height: 1.7;
}

a { color: #111; }

/* the frame — difference blend keeps it legible over anything below.
   z-index sits ABOVE #page-fade (9999) and #lab-loading so the top-left
   header stays constant across page changes: only the body content below
   fades/loads, the breadcrumb never blanks out. */
.crumbs {
  position: fixed; top: 0; left: 0; right: 0; z-index: 10000;
  mix-blend-mode: difference; color: #fff;
  padding: 14px 16px; pointer-events: none;
}
.crumbs a { color: #fff; text-decoration: none; pointer-events: auto; }
.crumbs a:hover { text-decoration: underline; }

.cap {
  position: fixed; left: 16px; bottom: 12px; right: 16px; z-index: 100;
  mix-blend-mode: difference; color: #fff;
  pointer-events: none;
}

/* top-right controls (⟳ reset, ♪ audio): bare glyphs, but the whole
   44×44 box is the hit area — the iOS/Android minimum tap target.
   Touch devices get a bigger glyph on top of that. */
.reset, .audio {
  position: fixed; top: 2px; z-index: 101;
  mix-blend-mode: difference; color: #fff;
  background: none; border: none; cursor: pointer;
  font: 22px/44px ui-monospace, Menlo, monospace;
  width: 44px; height: 44px; padding: 0; text-align: center;
  -webkit-tap-highlight-color: transparent;
}
.reset { right: 4px; }
.audio { right: 48px; }
@media (pointer: coarse) {
  .reset, .audio { font-size: 26px; }
}

.end {
  position: fixed; left: 16px; right: 16px; bottom: 12px; z-index: 100;
  mix-blend-mode: difference; color: #fff;
  text-align: center; pointer-events: none;
  display: none;
}

.audio.off { text-decoration: line-through; opacity: .6; }

/* page transitions (lab-nav.js): a white overlay fades pages in/out.
   Never animate body opacity — it isolates the mix-blend-mode frame and
   turns the difference-blended crumbs/captions white. The overlay sits
   on TOP (painted after), so body keeps blending against the real page. */
#page-fade { position: fixed; inset: 0; background: #fff; z-index: 9999;
             pointer-events: none; opacity: 0; transition: opacity .26s ease; }
#page-fade.show { opacity: 1; }
