/* ============================================================
   mtvchk.dev foundations
   Raw color pairs stay separate from the composed tokens so the
   contrast checker can read them and so pairs can be recombined.
   ============================================================ */

@font-face {
  font-family: "JetBrains Mono";
  src: url("../fonts/jetbrains-mono-latin.woff2") format("woff2-variations");
  font-weight: 100 800;
  font-style: normal;
  font-display: swap;
}

:root {
  color-scheme: light dark;

  --bg-light: #FFFFFF;
  --bg-dark: #0B0B0C;
  --ink-light: #111112;
  --ink-dark: #E8E6E3;
  --muted-light: #5C5C63;
  --muted-dark: #8A8A8F;
  --rule-light: #E2E2E4;
  --rule-dark: #232326;
  --accent-light: #8A5200;
  --accent-dark: #E8A33D;

  --bg: light-dark(var(--bg-light), var(--bg-dark));
  --ink: light-dark(var(--ink-light), var(--ink-dark));
  --muted: light-dark(var(--muted-light), var(--muted-dark));
  --rule: light-dark(var(--rule-light), var(--rule-dark));
  --accent: light-dark(var(--accent-light), var(--accent-dark));

  /* The hero glow is a dark-theme device: it reads as light coming off a
     screen. The light accent is a dark brown, so the same wash on white came
     out as a beige smudge with none of that meaning. Light gets no glow at
     all rather than a weaker version of the wrong idea.
     Held at full strength here and diluted per stop below, so one token can
     still switch the whole thing off. */
  --glow: light-dark(transparent, var(--accent));

  --mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Two axes, two units, and that split is the whole system.
     Across a line, space is measured in `ch`, because on a monospace page a
     character width is the real grid: 0.5ch between marks that belong to one
     token, 1ch between separate ones, 1.5ch for a hanging marker.
     Down the page, space is a multiple of --step, and only these multiples
     are allowed:
       1  ( 8px)  inside one component
       2  (16px)  between elements that belong together
       3  (24px)  component padding, and the page gutter
       4  (32px)  between blocks within a section
       6  (48px)  a page band
       8  (64px)  between sections
      12  (96px)  the opening band
     One documented half step survives, 1.5 (12px), and only as the vertical
     padding of an inline control: 8px would put the tap target under 44px and
     16px would make a button that is mostly air. Anything else on this axis
     is a mistake, not a refinement. */
  --step: 8px;
  --col: 72ch;

  accent-color: var(--accent);
}

*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  padding: calc(var(--step) * 6) calc(var(--step) * 3);
  background: var(--bg);
  color: var(--ink);
  font-family: var(--mono);
  /* Keeps line length stable if the fallback font paints first. */
  font-size-adjust: 0.52;
  font-size: clamp(14px, 0.5rem + 0.6vw, 16px);
  line-height: 1.6;
}

main { max-width: var(--col); margin-inline: auto; padding-top: calc(var(--step) * 4); }
.hero__inner { max-width: var(--col); margin-inline: auto; }

a { color: var(--accent); text-underline-offset: 0.2em; }
a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}

/* Paragraph and list rhythm came from the browser, which uses 1em and so
   quietly changed with the font size: 16px on a desktop against 14px on a
   phone, while every other gap on the page stayed on the 8px grid. */
p, main ul { margin-block: calc(var(--step) * 2); }

.muted { color: var(--muted); }

/* Selection in the brand pair rather than the platform blue, which is the one
   colour on the page that belongs to nobody. Same accent-on-background pair
   the primary button uses, so it is already in the contrast check. */
::selection {
  background: var(--accent);
  color: var(--bg);
}
/* The filled button is already accent on background, so the rule above would
   paint accent on accent and the address would vanish exactly when someone
   selects it to copy. */
.btn::selection {
  background: var(--ink);
  color: var(--bg);
}

/* Product tally, framed like a terminal readout rather than a headline
   number, because it sits next to the cards that back the claim up. */
.count {
  display: inline-flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.5ch;
  margin: 0 0 calc(var(--step) * 3);
  padding: calc(var(--step) * 1.5) calc(var(--step) * 3);
  border: 1px solid var(--accent);
}
.count b { color: var(--accent); }
.count span { color: var(--muted); }
/* The dash joins the total to its breakdown, so it only carries meaning while
   the two share a line. It lives in the stylesheet rather than the markup for
   that reason, and is marked decorative the way the status glyphs are, since
   it is punctuation and not information. */
.count span::before { content: "- " / ""; }

/* Below the width where the two halves fit on one line, the readout becomes
   two deliberate lines and the dash goes with the join it belonged to. Left in
   the markup it would have started the second line, reading as a stray bullet
   rather than as a connector. */
@media (max-width: 36rem) {
  .count {
    flex-direction: column;
    align-items: start;
    gap: 0;
  }
  .count span::before { content: none; }
}

/* Terse fact list: a chevron reads as "prompt output" for short label:value
   lines. ".how i work"'s full sentences keep the plain default bullet,
   this is only for the compact stack-style lines. */
.list--terse {
  list-style: none;
  margin: 0;
  padding: 0;
}
/* Hanging marker. Padding moves the whole item right and the matching
   negative indent pulls only the first line back, so the marker sits on the
   same left edge as every other block while a wrapped line lines up under the
   text above it. Not flex: the label and the value are separate nodes, and as
   flex items they would each become their own column. */
.list--terse li {
  padding-left: 1.5ch;
  text-indent: -1.5ch;
}
.list--terse li::before {
  content: "\003E";
  display: inline-block;
  width: 1.5ch;
  text-indent: 0;
  color: var(--accent);
}

/* ============================================================
   Wordmark
   Two literals, swapped by width. The reveal animates clip-path
   in whole-column steps so the art never renders a partial glyph.
   ============================================================ */

.vh {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.wordmark pre {
  margin: 0;
  font: inherit;
  line-height: 1.15;
  color: var(--ink);
  /* Scale the art to fill the container instead of letting it overflow.
     A monospace glyph advance is a fraction of the font size, not the
     whole of it: JetBrains Mono measures 0.5673em here, so dividing by
     the column count alone renders the art at roughly half the width it
     should have. 0.58 is that measured ratio plus about 2 percent of
     slack, so a fallback font with slightly wider glyphs still fits.
     The rem cap is a ceiling, not the usual case. */
  font-size: min(1.5rem, calc(100cqw / (var(--cols) * 0.58)));
  animation: reveal 900ms steps(var(--cols)) 120ms both;
}

.wordmark { container-type: inline-size; }

.wordmark__wide { --cols: 55; }
.wordmark__narrow { --cols: 27; display: none; }

@container (max-width: 34rem) {
  .wordmark__wide { display: none; }
  .wordmark__narrow { display: block; }
}

@keyframes reveal {
  from { clip-path: inset(0 100% 0 0); }
  to   { clip-path: inset(0 0 0 0); }
}

.wordmark__cursor {
  display: inline-block;
  width: 1ch;
  height: 1.15em;
  vertical-align: text-bottom;
  background: var(--accent);
  animation: blink 900ms steps(1) 1020ms 4 both;
}

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

@media (prefers-reduced-motion: reduce) {
  .wordmark pre { animation: none; clip-path: none; }
  .wordmark__cursor { animation: none; opacity: 1; }
  .brand-mark__type { animation: none; clip-path: none; }
  .brand-mark__cursor { animation: none; opacity: 1; }
}

/* ============================================================
   Hero
   Full-bleed glow band before <main>. The wordmark art from the
   design system is not used here; .wordmark/.vh stay defined below
   for design-system/03-wordmark.html, which still demonstrates them.
   ============================================================ */

.hero {
  position: relative;
  /* Cancels body's own padding so the glow reaches the viewport edge,
     then re-applies the hero's own, larger padding inside that. */
  margin: calc(-1 * var(--step) * 6) calc(-1 * var(--step) * 3) 0;
  padding: calc(var(--step) * 12) calc(var(--step) * 3) calc(var(--step) * 6);
  /* Six stops on a falloff that starts slow and ends long, instead of two on
     a straight ramp. A linear ramp cut off at 70% is what made this read as a
     painted shape: the slope changes abruptly where it lands on zero, and the
     eye resolves that as an edge even though no edge is drawn. Light does not
     end anywhere, it thins out, so the tail now runs to the full extent of
     the ellipse and the strength drops fastest near the source.
     The extent is close to what the two-stop version reached, on purpose.
     Easing the curve and widening the ellipse at the same time washed the
     whole top of the band in warm and the light stopped reading as light:
     it needs dark next to it to be legible as a source at all.
     No `in oklab` on the gradient itself: an unsupported interpolation
     keyword invalidates the whole declaration, and this one also carries the
     background colour. The stops sit close enough that sRGB between them
     costs nothing. */
  background:
    radial-gradient(ellipse 54% 46% at 74% 20%,
      color-mix(in oklab, var(--glow) 20%, transparent) 0%,
      color-mix(in oklab, var(--glow) 16.5%, transparent) 15%,
      color-mix(in oklab, var(--glow) 11%, transparent) 32%,
      color-mix(in oklab, var(--glow) 6%, transparent) 50%,
      color-mix(in oklab, var(--glow) 2.6%, transparent) 68%,
      color-mix(in oklab, var(--glow) 0.8%, transparent) 84%,
      transparent 100%),
    var(--bg);
}

.hero__inner { position: relative; z-index: 1; }
/* The field is positioned and would otherwise paint over the in-flow content
   that follows it. */
main { position: relative; z-index: 1; }

/* Sparse character field behind the hero. It is decoration, so it lives
   entirely in CSS rather than in the markup: two SVG masks tinted with the
   theme tokens, which is why one asset covers light and dark. Keeping it out
   of the DOM means a stale or missing stylesheet degrades to a plain band,
   where the earlier markup-based version instead spilled a few hundred loose
   glyphs into the layout and pushed the page down.
   The horizontal fade is baked into each SVG, so no mask compositing and no
   vendor-specific composite keywords are needed.
   Generated by tools/build-noise.mjs; regenerate rather than hand-edit. */
/* One radial shapes both layers. It replaces two separate fades that used to
   live in different places: a horizontal one baked into the SVG and a
   vertical one on the paint. Collapsing them is what frees the tile to be
   sized in em and repeated, since anything baked into the SVG would repeat
   with it and band the field.

   The shape is doing real work, not decoration. The field stops before the
   copy starts, which is why the band no longer ends in a hard edge, and why
   the texture no longer sits under the paragraph and the fact list where
   large faint glyphs and small text blur into each other. What is left says
   something: the noise belongs to the chrome at the top of the band, and the
   page gets quieter as it moves into what there is to read.

   Shaping the paint rather than the mask keeps this to one property. A
   second CSS mask layer would need mask-composite, which Safari still spells
   its own way; multiplying the colour the mask reveals is the same
   arithmetic without that. */
.hero::before, .hero::after {
  content: "";
  position: absolute;
  /* Runs past the band's own bottom edge, as far as the first section
     heading, so the field is a property of the top of the page rather than of
     one element. The band used to clip it, which is why shaping the falloff
     also shortened it. */
  inset: 0 0 calc(-1 * var(--step) * 4) 0;
  pointer-events: none;
  -webkit-mask-repeat: repeat;
  mask-repeat: repeat;
  /* Sized against the type rather than the viewport. Scaling the tile to the
     element's width made one cell 23px on a desktop and 7px on a phone, well
     under the body type there, so the field turned into grain nobody could
     read as characters. In em it keeps the same relation to the text
     everywhere, and the tile repeats to cover whatever is left. The clamp
     stops short of full parity on the way down: a phone fits only twenty
     columns at the desktop cell size, which reads as a handful of scattered
     digits rather than as a field. */
  -webkit-mask-size: calc(56 * clamp(1em, 1.9vw, 1.5em)) auto;
  mask-size: calc(56 * clamp(1em, 1.9vw, 1.5em)) auto;
}
.hero::before {
  background: radial-gradient(ellipse 50% 96% at 50% 4%, var(--muted) 0 45%, transparent 100%);
  opacity: 0.14;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 56 126'%3E%3Cg fill='%23fff' font-family='monospace' font-size='1.76' text-anchor='middle'%3E%3Ctext x='0.5' y='5.6'%3E+%3C/text%3E%3Ctext x='11.5' y='3.6'%3E0%3C/text%3E%3Ctext x='14.5' y='3.6'%3E1%3C/text%3E%3Ctext x='22.5' y='5.6'%3E+%3C/text%3E%3Ctext x='29.5' y='1.6'%3E:%3C/text%3E%3Ctext x='33.5' y='3.6'%3E1%3C/text%3E%3Ctext x='38.5' y='5.6'%3E1%3C/text%3E%3Ctext x='40.5' y='3.6'%3E:%3C/text%3E%3Ctext x='46.5' y='1.6'%3E.%3C/text%3E%3Ctext x='50.5' y='1.6'%3E.%3C/text%3E%3Ctext x='54.5' y='3.6'%3E:%3C/text%3E%3Ctext x='1.5' y='11.6'%3E1%3C/text%3E%3Ctext x='13.5' y='11.6'%3E1%3C/text%3E%3Ctext x='29.5' y='9.6'%3E1%3C/text%3E%3Ctext x='34.5' y='9.6'%3E:%3C/text%3E%3Ctext x='46.5' y='11.6'%3E.%3C/text%3E%3Ctext x='0.5' y='15.6'%3E1%3C/text%3E%3Ctext x='6.5' y='17.6'%3E:%3C/text%3E%3Ctext x='9.5' y='13.6'%3E1%3C/text%3E%3Ctext x='19.5' y='17.6'%3E:%3C/text%3E%3Ctext x='22.5' y='13.6'%3E1%3C/text%3E%3Ctext x='39.5' y='13.6'%3E:%3C/text%3E%3Ctext x='45.5' y='17.6'%3E0%3C/text%3E%3Ctext x='48.5' y='13.6'%3E1%3C/text%3E%3Ctext x='52.5' y='17.6'%3E1%3C/text%3E%3Ctext x='7.5' y='23.6'%3E0%3C/text%3E%3Ctext x='18.5' y='19.6'%3E1%3C/text%3E%3Ctext x='21.5' y='19.6'%3E.%3C/text%3E%3Ctext x='24.5' y='23.6'%3E.%3C/text%3E%3Ctext x='35.5' y='23.6'%3E.%3C/text%3E%3Ctext x='38.5' y='23.6'%3E0%3C/text%3E%3Ctext x='53.5' y='21.6'%3E+%3C/text%3E%3Ctext x='4.5' y='29.6'%3E.%3C/text%3E%3Ctext x='11.5' y='29.6'%3E0%3C/text%3E%3Ctext x='12.5' y='29.6'%3E.%3C/text%3E%3Ctext x='20.5' y='29.6'%3E+%3C/text%3E%3Ctext x='24.5' y='27.6'%3E.%3C/text%3E%3Ctext x='32.5' y='29.6'%3E:%3C/text%3E%3Ctext x='37.5' y='27.6'%3E:%3C/text%3E%3Ctext x='42.5' y='27.6'%3E:%3C/text%3E%3Ctext x='47.5' y='29.6'%3E1%3C/text%3E%3Ctext x='48.5' y='25.6'%3E:%3C/text%3E%3Ctext x='54.5' y='29.6'%3E:%3C/text%3E%3Ctext x='2.5' y='35.6'%3E0%3C/text%3E%3Ctext x='8.5' y='35.6'%3E:%3C/text%3E%3Ctext x='23.5' y='33.6'%3E:%3C/text%3E%3Ctext x='24.5' y='31.6'%3E1%3C/text%3E%3Ctext x='31.5' y='35.6'%3E1%3C/text%3E%3Ctext x='32.5' y='31.6'%3E:%3C/text%3E%3Ctext x='36.5' y='33.6'%3E0%3C/text%3E%3Ctext x='40.5' y='33.6'%3E:%3C/text%3E%3Ctext x='50.5' y='35.6'%3E+%3C/text%3E%3Ctext x='53.5' y='35.6'%3E+%3C/text%3E%3Ctext x='3.5' y='41.6'%3E:%3C/text%3E%3Ctext x='8.5' y='39.6'%3E.%3C/text%3E%3Ctext x='13.5' y='41.6'%3E1%3C/text%3E%3Ctext x='16.5' y='41.6'%3E.%3C/text%3E%3Ctext x='23.5' y='39.6'%3E+%3C/text%3E%3Ctext x='33.5' y='37.6'%3E+%3C/text%3E%3Ctext x='37.5' y='37.6'%3E.%3C/text%3E%3Ctext x='40.5' y='37.6'%3E+%3C/text%3E%3Ctext x='51.5' y='37.6'%3E+%3C/text%3E%3Ctext x='52.5' y='41.6'%3E:%3C/text%3E%3Ctext x='10.5' y='43.6'%3E0%3C/text%3E%3Ctext x='14.5' y='47.6'%3E1%3C/text%3E%3Ctext x='24.5' y='47.6'%3E1%3C/text%3E%3Ctext x='31.5' y='47.6'%3E:%3C/text%3E%3Ctext x='35.5' y='47.6'%3E0%3C/text%3E%3Ctext x='36.5' y='45.6'%3E0%3C/text%3E%3Ctext x='44.5' y='45.6'%3E.%3C/text%3E%3Ctext x='50.5' y='47.6'%3E0%3C/text%3E%3Ctext x='52.5' y='45.6'%3E0%3C/text%3E%3Ctext x='2.5' y='53.6'%3E0%3C/text%3E%3Ctext x='4.5' y='51.6'%3E1%3C/text%3E%3Ctext x='10.5' y='51.6'%3E1%3C/text%3E%3Ctext x='14.5' y='51.6'%3E0%3C/text%3E%3Ctext x='23.5' y='51.6'%3E1%3C/text%3E%3Ctext x='40.5' y='53.6'%3E:%3C/text%3E%3Ctext x='45.5' y='53.6'%3E0%3C/text%3E%3Ctext x='51.5' y='53.6'%3E:%3C/text%3E%3Ctext x='0.5' y='59.6'%3E1%3C/text%3E%3Ctext x='4.5' y='59.6'%3E+%3C/text%3E%3Ctext x='11.5' y='59.6'%3E0%3C/text%3E%3Ctext x='30.5' y='57.6'%3E.%3C/text%3E%3Ctext x='37.5' y='57.6'%3E+%3C/text%3E%3Ctext x='43.5' y='55.6'%3E1%3C/text%3E%3Ctext x='46.5' y='59.6'%3E+%3C/text%3E%3Ctext x='52.5' y='59.6'%3E.%3C/text%3E%3Ctext x='0.5' y='63.6'%3E:%3C/text%3E%3Ctext x='24.5' y='61.6'%3E.%3C/text%3E%3Ctext x='30.5' y='63.6'%3E:%3C/text%3E%3Ctext x='35.5' y='63.6'%3E:%3C/text%3E%3Ctext x='55.5' y='61.6'%3E0%3C/text%3E%3Ctext x='1.5' y='67.6'%3E:%3C/text%3E%3Ctext x='9.5' y='71.6'%3E0%3C/text%3E%3Ctext x='15.5' y='71.6'%3E1%3C/text%3E%3Ctext x='24.5' y='67.6'%3E.%3C/text%3E%3Ctext x='33.5' y='67.6'%3E:%3C/text%3E%3Ctext x='40.5' y='67.6'%3E.%3C/text%3E%3Ctext x='2.5' y='77.6'%3E:%3C/text%3E%3Ctext x='7.5' y='75.6'%3E.%3C/text%3E%3Ctext x='11.5' y='77.6'%3E0%3C/text%3E%3Ctext x='18.5' y='73.6'%3E0%3C/text%3E%3Ctext x='20.5' y='73.6'%3E+%3C/text%3E%3Ctext x='33.5' y='75.6'%3E:%3C/text%3E%3Ctext x='38.5' y='73.6'%3E:%3C/text%3E%3Ctext x='47.5' y='73.6'%3E+%3C/text%3E%3Ctext x='49.5' y='75.6'%3E:%3C/text%3E%3Ctext x='3.5' y='83.6'%3E1%3C/text%3E%3Ctext x='11.5' y='83.6'%3E+%3C/text%3E%3Ctext x='22.5' y='79.6'%3E1%3C/text%3E%3Ctext x='27.5' y='79.6'%3E0%3C/text%3E%3Ctext x='33.5' y='83.6'%3E:%3C/text%3E%3Ctext x='37.5' y='79.6'%3E+%3C/text%3E%3Ctext x='45.5' y='83.6'%3E:%3C/text%3E%3Ctext x='49.5' y='79.6'%3E1%3C/text%3E%3Ctext x='52.5' y='79.6'%3E0%3C/text%3E%3Ctext x='6.5' y='87.6'%3E1%3C/text%3E%3Ctext x='10.5' y='85.6'%3E1%3C/text%3E%3Ctext x='32.5' y='87.6'%3E:%3C/text%3E%3Ctext x='36.5' y='89.6'%3E:%3C/text%3E%3Ctext x='42.5' y='89.6'%3E1%3C/text%3E%3Ctext x='55.5' y='85.6'%3E.%3C/text%3E%3Ctext x='0.5' y='91.6'%3E.%3C/text%3E%3Ctext x='5.5' y='95.6'%3E0%3C/text%3E%3Ctext x='8.5' y='93.6'%3E:%3C/text%3E%3Ctext x='13.5' y='91.6'%3E:%3C/text%3E%3Ctext x='18.5' y='95.6'%3E+%3C/text%3E%3Ctext x='21.5' y='91.6'%3E0%3C/text%3E%3Ctext x='24.5' y='95.6'%3E0%3C/text%3E%3Ctext x='31.5' y='93.6'%3E.%3C/text%3E%3Ctext x='43.5' y='91.6'%3E0%3C/text%3E%3Ctext x='45.5' y='95.6'%3E1%3C/text%3E%3Ctext x='49.5' y='93.6'%3E0%3C/text%3E%3Ctext x='53.5' y='91.6'%3E+%3C/text%3E%3Ctext x='4.5' y='101.6'%3E+%3C/text%3E%3Ctext x='12.5' y='101.6'%3E.%3C/text%3E%3Ctext x='21.5' y='99.6'%3E+%3C/text%3E%3Ctext x='36.5' y='101.6'%3E+%3C/text%3E%3Ctext x='42.5' y='99.6'%3E.%3C/text%3E%3Ctext x='50.5' y='97.6'%3E+%3C/text%3E%3Ctext x='1.5' y='103.6'%3E.%3C/text%3E%3Ctext x='10.5' y='107.6'%3E.%3C/text%3E%3Ctext x='14.5' y='105.6'%3E+%3C/text%3E%3Ctext x='17.5' y='105.6'%3E1%3C/text%3E%3Ctext x='29.5' y='105.6'%3E+%3C/text%3E%3Ctext x='33.5' y='103.6'%3E:%3C/text%3E%3Ctext x='41.5' y='105.6'%3E+%3C/text%3E%3Ctext x='47.5' y='105.6'%3E:%3C/text%3E%3Ctext x='55.5' y='105.6'%3E:%3C/text%3E%3Ctext x='0.5' y='111.6'%3E:%3C/text%3E%3Ctext x='6.5' y='109.6'%3E0%3C/text%3E%3Ctext x='8.5' y='111.6'%3E0%3C/text%3E%3Ctext x='14.5' y='111.6'%3E1%3C/text%3E%3Ctext x='21.5' y='111.6'%3E:%3C/text%3E%3Ctext x='27.5' y='109.6'%3E+%3C/text%3E%3Ctext x='28.5' y='113.6'%3E:%3C/text%3E%3Ctext x='35.5' y='109.6'%3E+%3C/text%3E%3Ctext x='36.5' y='109.6'%3E1%3C/text%3E%3Ctext x='41.5' y='109.6'%3E.%3C/text%3E%3Ctext x='47.5' y='109.6'%3E1%3C/text%3E%3Ctext x='50.5' y='113.6'%3E+%3C/text%3E%3Ctext x='54.5' y='111.6'%3E:%3C/text%3E%3Ctext x='5.5' y='115.6'%3E:%3C/text%3E%3Ctext x='12.5' y='117.6'%3E.%3C/text%3E%3Ctext x='18.5' y='115.6'%3E.%3C/text%3E%3Ctext x='24.5' y='115.6'%3E+%3C/text%3E%3Ctext x='30.5' y='117.6'%3E1%3C/text%3E%3Ctext x='33.5' y='119.6'%3E.%3C/text%3E%3Ctext x='39.5' y='117.6'%3E+%3C/text%3E%3Ctext x='41.5' y='117.6'%3E:%3C/text%3E%3Ctext x='44.5' y='115.6'%3E.%3C/text%3E%3Ctext x='50.5' y='115.6'%3E1%3C/text%3E%3Ctext x='53.5' y='119.6'%3E+%3C/text%3E%3Ctext x='2.5' y='121.6'%3E:%3C/text%3E%3Ctext x='4.5' y='125.6'%3E1%3C/text%3E%3Ctext x='15.5' y='125.6'%3E1%3C/text%3E%3Ctext x='18.5' y='121.6'%3E0%3C/text%3E%3Ctext x='21.5' y='121.6'%3E0%3C/text%3E%3Ctext x='27.5' y='121.6'%3E1%3C/text%3E%3Ctext x='29.5' y='123.6'%3E1%3C/text%3E%3Ctext x='35.5' y='123.6'%3E:%3C/text%3E%3Ctext x='43.5' y='121.6'%3E.%3C/text%3E%3Ctext x='47.5' y='121.6'%3E:%3C/text%3E%3Ctext x='50.5' y='125.6'%3E0%3C/text%3E%3Ctext x='52.5' y='125.6'%3E0%3C/text%3E%3C/g%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 56 126'%3E%3Cg fill='%23fff' font-family='monospace' font-size='1.76' text-anchor='middle'%3E%3Ctext x='0.5' y='5.6'%3E+%3C/text%3E%3Ctext x='11.5' y='3.6'%3E0%3C/text%3E%3Ctext x='14.5' y='3.6'%3E1%3C/text%3E%3Ctext x='22.5' y='5.6'%3E+%3C/text%3E%3Ctext x='29.5' y='1.6'%3E:%3C/text%3E%3Ctext x='33.5' y='3.6'%3E1%3C/text%3E%3Ctext x='38.5' y='5.6'%3E1%3C/text%3E%3Ctext x='40.5' y='3.6'%3E:%3C/text%3E%3Ctext x='46.5' y='1.6'%3E.%3C/text%3E%3Ctext x='50.5' y='1.6'%3E.%3C/text%3E%3Ctext x='54.5' y='3.6'%3E:%3C/text%3E%3Ctext x='1.5' y='11.6'%3E1%3C/text%3E%3Ctext x='13.5' y='11.6'%3E1%3C/text%3E%3Ctext x='29.5' y='9.6'%3E1%3C/text%3E%3Ctext x='34.5' y='9.6'%3E:%3C/text%3E%3Ctext x='46.5' y='11.6'%3E.%3C/text%3E%3Ctext x='0.5' y='15.6'%3E1%3C/text%3E%3Ctext x='6.5' y='17.6'%3E:%3C/text%3E%3Ctext x='9.5' y='13.6'%3E1%3C/text%3E%3Ctext x='19.5' y='17.6'%3E:%3C/text%3E%3Ctext x='22.5' y='13.6'%3E1%3C/text%3E%3Ctext x='39.5' y='13.6'%3E:%3C/text%3E%3Ctext x='45.5' y='17.6'%3E0%3C/text%3E%3Ctext x='48.5' y='13.6'%3E1%3C/text%3E%3Ctext x='52.5' y='17.6'%3E1%3C/text%3E%3Ctext x='7.5' y='23.6'%3E0%3C/text%3E%3Ctext x='18.5' y='19.6'%3E1%3C/text%3E%3Ctext x='21.5' y='19.6'%3E.%3C/text%3E%3Ctext x='24.5' y='23.6'%3E.%3C/text%3E%3Ctext x='35.5' y='23.6'%3E.%3C/text%3E%3Ctext x='38.5' y='23.6'%3E0%3C/text%3E%3Ctext x='53.5' y='21.6'%3E+%3C/text%3E%3Ctext x='4.5' y='29.6'%3E.%3C/text%3E%3Ctext x='11.5' y='29.6'%3E0%3C/text%3E%3Ctext x='12.5' y='29.6'%3E.%3C/text%3E%3Ctext x='20.5' y='29.6'%3E+%3C/text%3E%3Ctext x='24.5' y='27.6'%3E.%3C/text%3E%3Ctext x='32.5' y='29.6'%3E:%3C/text%3E%3Ctext x='37.5' y='27.6'%3E:%3C/text%3E%3Ctext x='42.5' y='27.6'%3E:%3C/text%3E%3Ctext x='47.5' y='29.6'%3E1%3C/text%3E%3Ctext x='48.5' y='25.6'%3E:%3C/text%3E%3Ctext x='54.5' y='29.6'%3E:%3C/text%3E%3Ctext x='2.5' y='35.6'%3E0%3C/text%3E%3Ctext x='8.5' y='35.6'%3E:%3C/text%3E%3Ctext x='23.5' y='33.6'%3E:%3C/text%3E%3Ctext x='24.5' y='31.6'%3E1%3C/text%3E%3Ctext x='31.5' y='35.6'%3E1%3C/text%3E%3Ctext x='32.5' y='31.6'%3E:%3C/text%3E%3Ctext x='36.5' y='33.6'%3E0%3C/text%3E%3Ctext x='40.5' y='33.6'%3E:%3C/text%3E%3Ctext x='50.5' y='35.6'%3E+%3C/text%3E%3Ctext x='53.5' y='35.6'%3E+%3C/text%3E%3Ctext x='3.5' y='41.6'%3E:%3C/text%3E%3Ctext x='8.5' y='39.6'%3E.%3C/text%3E%3Ctext x='13.5' y='41.6'%3E1%3C/text%3E%3Ctext x='16.5' y='41.6'%3E.%3C/text%3E%3Ctext x='23.5' y='39.6'%3E+%3C/text%3E%3Ctext x='33.5' y='37.6'%3E+%3C/text%3E%3Ctext x='37.5' y='37.6'%3E.%3C/text%3E%3Ctext x='40.5' y='37.6'%3E+%3C/text%3E%3Ctext x='51.5' y='37.6'%3E+%3C/text%3E%3Ctext x='52.5' y='41.6'%3E:%3C/text%3E%3Ctext x='10.5' y='43.6'%3E0%3C/text%3E%3Ctext x='14.5' y='47.6'%3E1%3C/text%3E%3Ctext x='24.5' y='47.6'%3E1%3C/text%3E%3Ctext x='31.5' y='47.6'%3E:%3C/text%3E%3Ctext x='35.5' y='47.6'%3E0%3C/text%3E%3Ctext x='36.5' y='45.6'%3E0%3C/text%3E%3Ctext x='44.5' y='45.6'%3E.%3C/text%3E%3Ctext x='50.5' y='47.6'%3E0%3C/text%3E%3Ctext x='52.5' y='45.6'%3E0%3C/text%3E%3Ctext x='2.5' y='53.6'%3E0%3C/text%3E%3Ctext x='4.5' y='51.6'%3E1%3C/text%3E%3Ctext x='10.5' y='51.6'%3E1%3C/text%3E%3Ctext x='14.5' y='51.6'%3E0%3C/text%3E%3Ctext x='23.5' y='51.6'%3E1%3C/text%3E%3Ctext x='40.5' y='53.6'%3E:%3C/text%3E%3Ctext x='45.5' y='53.6'%3E0%3C/text%3E%3Ctext x='51.5' y='53.6'%3E:%3C/text%3E%3Ctext x='0.5' y='59.6'%3E1%3C/text%3E%3Ctext x='4.5' y='59.6'%3E+%3C/text%3E%3Ctext x='11.5' y='59.6'%3E0%3C/text%3E%3Ctext x='30.5' y='57.6'%3E.%3C/text%3E%3Ctext x='37.5' y='57.6'%3E+%3C/text%3E%3Ctext x='43.5' y='55.6'%3E1%3C/text%3E%3Ctext x='46.5' y='59.6'%3E+%3C/text%3E%3Ctext x='52.5' y='59.6'%3E.%3C/text%3E%3Ctext x='0.5' y='63.6'%3E:%3C/text%3E%3Ctext x='24.5' y='61.6'%3E.%3C/text%3E%3Ctext x='30.5' y='63.6'%3E:%3C/text%3E%3Ctext x='35.5' y='63.6'%3E:%3C/text%3E%3Ctext x='55.5' y='61.6'%3E0%3C/text%3E%3Ctext x='1.5' y='67.6'%3E:%3C/text%3E%3Ctext x='9.5' y='71.6'%3E0%3C/text%3E%3Ctext x='15.5' y='71.6'%3E1%3C/text%3E%3Ctext x='24.5' y='67.6'%3E.%3C/text%3E%3Ctext x='33.5' y='67.6'%3E:%3C/text%3E%3Ctext x='40.5' y='67.6'%3E.%3C/text%3E%3Ctext x='2.5' y='77.6'%3E:%3C/text%3E%3Ctext x='7.5' y='75.6'%3E.%3C/text%3E%3Ctext x='11.5' y='77.6'%3E0%3C/text%3E%3Ctext x='18.5' y='73.6'%3E0%3C/text%3E%3Ctext x='20.5' y='73.6'%3E+%3C/text%3E%3Ctext x='33.5' y='75.6'%3E:%3C/text%3E%3Ctext x='38.5' y='73.6'%3E:%3C/text%3E%3Ctext x='47.5' y='73.6'%3E+%3C/text%3E%3Ctext x='49.5' y='75.6'%3E:%3C/text%3E%3Ctext x='3.5' y='83.6'%3E1%3C/text%3E%3Ctext x='11.5' y='83.6'%3E+%3C/text%3E%3Ctext x='22.5' y='79.6'%3E1%3C/text%3E%3Ctext x='27.5' y='79.6'%3E0%3C/text%3E%3Ctext x='33.5' y='83.6'%3E:%3C/text%3E%3Ctext x='37.5' y='79.6'%3E+%3C/text%3E%3Ctext x='45.5' y='83.6'%3E:%3C/text%3E%3Ctext x='49.5' y='79.6'%3E1%3C/text%3E%3Ctext x='52.5' y='79.6'%3E0%3C/text%3E%3Ctext x='6.5' y='87.6'%3E1%3C/text%3E%3Ctext x='10.5' y='85.6'%3E1%3C/text%3E%3Ctext x='32.5' y='87.6'%3E:%3C/text%3E%3Ctext x='36.5' y='89.6'%3E:%3C/text%3E%3Ctext x='42.5' y='89.6'%3E1%3C/text%3E%3Ctext x='55.5' y='85.6'%3E.%3C/text%3E%3Ctext x='0.5' y='91.6'%3E.%3C/text%3E%3Ctext x='5.5' y='95.6'%3E0%3C/text%3E%3Ctext x='8.5' y='93.6'%3E:%3C/text%3E%3Ctext x='13.5' y='91.6'%3E:%3C/text%3E%3Ctext x='18.5' y='95.6'%3E+%3C/text%3E%3Ctext x='21.5' y='91.6'%3E0%3C/text%3E%3Ctext x='24.5' y='95.6'%3E0%3C/text%3E%3Ctext x='31.5' y='93.6'%3E.%3C/text%3E%3Ctext x='43.5' y='91.6'%3E0%3C/text%3E%3Ctext x='45.5' y='95.6'%3E1%3C/text%3E%3Ctext x='49.5' y='93.6'%3E0%3C/text%3E%3Ctext x='53.5' y='91.6'%3E+%3C/text%3E%3Ctext x='4.5' y='101.6'%3E+%3C/text%3E%3Ctext x='12.5' y='101.6'%3E.%3C/text%3E%3Ctext x='21.5' y='99.6'%3E+%3C/text%3E%3Ctext x='36.5' y='101.6'%3E+%3C/text%3E%3Ctext x='42.5' y='99.6'%3E.%3C/text%3E%3Ctext x='50.5' y='97.6'%3E+%3C/text%3E%3Ctext x='1.5' y='103.6'%3E.%3C/text%3E%3Ctext x='10.5' y='107.6'%3E.%3C/text%3E%3Ctext x='14.5' y='105.6'%3E+%3C/text%3E%3Ctext x='17.5' y='105.6'%3E1%3C/text%3E%3Ctext x='29.5' y='105.6'%3E+%3C/text%3E%3Ctext x='33.5' y='103.6'%3E:%3C/text%3E%3Ctext x='41.5' y='105.6'%3E+%3C/text%3E%3Ctext x='47.5' y='105.6'%3E:%3C/text%3E%3Ctext x='55.5' y='105.6'%3E:%3C/text%3E%3Ctext x='0.5' y='111.6'%3E:%3C/text%3E%3Ctext x='6.5' y='109.6'%3E0%3C/text%3E%3Ctext x='8.5' y='111.6'%3E0%3C/text%3E%3Ctext x='14.5' y='111.6'%3E1%3C/text%3E%3Ctext x='21.5' y='111.6'%3E:%3C/text%3E%3Ctext x='27.5' y='109.6'%3E+%3C/text%3E%3Ctext x='28.5' y='113.6'%3E:%3C/text%3E%3Ctext x='35.5' y='109.6'%3E+%3C/text%3E%3Ctext x='36.5' y='109.6'%3E1%3C/text%3E%3Ctext x='41.5' y='109.6'%3E.%3C/text%3E%3Ctext x='47.5' y='109.6'%3E1%3C/text%3E%3Ctext x='50.5' y='113.6'%3E+%3C/text%3E%3Ctext x='54.5' y='111.6'%3E:%3C/text%3E%3Ctext x='5.5' y='115.6'%3E:%3C/text%3E%3Ctext x='12.5' y='117.6'%3E.%3C/text%3E%3Ctext x='18.5' y='115.6'%3E.%3C/text%3E%3Ctext x='24.5' y='115.6'%3E+%3C/text%3E%3Ctext x='30.5' y='117.6'%3E1%3C/text%3E%3Ctext x='33.5' y='119.6'%3E.%3C/text%3E%3Ctext x='39.5' y='117.6'%3E+%3C/text%3E%3Ctext x='41.5' y='117.6'%3E:%3C/text%3E%3Ctext x='44.5' y='115.6'%3E.%3C/text%3E%3Ctext x='50.5' y='115.6'%3E1%3C/text%3E%3Ctext x='53.5' y='119.6'%3E+%3C/text%3E%3Ctext x='2.5' y='121.6'%3E:%3C/text%3E%3Ctext x='4.5' y='125.6'%3E1%3C/text%3E%3Ctext x='15.5' y='125.6'%3E1%3C/text%3E%3Ctext x='18.5' y='121.6'%3E0%3C/text%3E%3Ctext x='21.5' y='121.6'%3E0%3C/text%3E%3Ctext x='27.5' y='121.6'%3E1%3C/text%3E%3Ctext x='29.5' y='123.6'%3E1%3C/text%3E%3Ctext x='35.5' y='123.6'%3E:%3C/text%3E%3Ctext x='43.5' y='121.6'%3E.%3C/text%3E%3Ctext x='47.5' y='121.6'%3E:%3C/text%3E%3Ctext x='50.5' y='125.6'%3E0%3C/text%3E%3Ctext x='52.5' y='125.6'%3E0%3C/text%3E%3C/g%3E%3C/svg%3E");
}

.hero::after {
  background: radial-gradient(ellipse 50% 96% at 50% 4%, var(--accent) 0 45%, transparent 100%);
  opacity: 0.22;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 56 126'%3E%3Cg fill='%23fff' font-family='monospace' font-size='1.76' text-anchor='middle'%3E%3Ctext x='6.5' y='5.6'%3E1%3C/text%3E%3Ctext x='18.5' y='1.6'%3E0%3C/text%3E%3Ctext x='25.5' y='1.6'%3E:%3C/text%3E%3Ctext x='7.5' y='9.6'%3E1%3C/text%3E%3Ctext x='8.5' y='11.6'%3E:%3C/text%3E%3Ctext x='17.5' y='11.6'%3E1%3C/text%3E%3Ctext x='20.5' y='7.6'%3E.%3C/text%3E%3Ctext x='24.5' y='7.6'%3E+%3C/text%3E%3Ctext x='38.5' y='11.6'%3E:%3C/text%3E%3Ctext x='42.5' y='11.6'%3E:%3C/text%3E%3Ctext x='50.5' y='9.6'%3E+%3C/text%3E%3Ctext x='52.5' y='11.6'%3E0%3C/text%3E%3Ctext x='12.5' y='15.6'%3E.%3C/text%3E%3Ctext x='27.5' y='17.6'%3E1%3C/text%3E%3Ctext x='28.5' y='15.6'%3E+%3C/text%3E%3Ctext x='32.5' y='17.6'%3E.%3C/text%3E%3Ctext x='41.5' y='13.6'%3E:%3C/text%3E%3Ctext x='0.5' y='23.6'%3E0%3C/text%3E%3Ctext x='11.5' y='23.6'%3E:%3C/text%3E%3Ctext x='13.5' y='21.6'%3E:%3C/text%3E%3Ctext x='28.5' y='19.6'%3E.%3C/text%3E%3Ctext x='41.5' y='21.6'%3E.%3C/text%3E%3Ctext x='44.5' y='21.6'%3E0%3C/text%3E%3Ctext x='49.5' y='19.6'%3E.%3C/text%3E%3Ctext x='3.5' y='27.6'%3E1%3C/text%3E%3Ctext x='16.5' y='27.6'%3E:%3C/text%3E%3Ctext x='28.5' y='25.6'%3E:%3C/text%3E%3Ctext x='4.5' y='35.6'%3E.%3C/text%3E%3Ctext x='15.5' y='33.6'%3E+%3C/text%3E%3Ctext x='16.5' y='33.6'%3E+%3C/text%3E%3Ctext x='44.5' y='31.6'%3E.%3C/text%3E%3Ctext x='5.5' y='37.6'%3E:%3C/text%3E%3Ctext x='26.5' y='41.6'%3E0%3C/text%3E%3Ctext x='28.5' y='41.6'%3E:%3C/text%3E%3Ctext x='45.5' y='39.6'%3E:%3C/text%3E%3Ctext x='1.5' y='45.6'%3E1%3C/text%3E%3Ctext x='7.5' y='43.6'%3E+%3C/text%3E%3Ctext x='16.5' y='43.6'%3E.%3C/text%3E%3Ctext x='22.5' y='43.6'%3E1%3C/text%3E%3Ctext x='41.5' y='45.6'%3E1%3C/text%3E%3Ctext x='16.5' y='49.6'%3E:%3C/text%3E%3Ctext x='24.5' y='49.6'%3E.%3C/text%3E%3Ctext x='31.5' y='51.6'%3E0%3C/text%3E%3Ctext x='32.5' y='53.6'%3E+%3C/text%3E%3Ctext x='39.5' y='51.6'%3E.%3C/text%3E%3Ctext x='55.5' y='53.6'%3E.%3C/text%3E%3Ctext x='12.5' y='57.6'%3E0%3C/text%3E%3Ctext x='16.5' y='57.6'%3E+%3C/text%3E%3Ctext x='20.5' y='57.6'%3E:%3C/text%3E%3Ctext x='24.5' y='55.6'%3E0%3C/text%3E%3Ctext x='35.5' y='57.6'%3E0%3C/text%3E%3Ctext x='49.5' y='55.6'%3E:%3C/text%3E%3Ctext x='6.5' y='65.6'%3E.%3C/text%3E%3Ctext x='8.5' y='63.6'%3E+%3C/text%3E%3Ctext x='13.5' y='61.6'%3E+%3C/text%3E%3Ctext x='18.5' y='63.6'%3E+%3C/text%3E%3Ctext x='20.5' y='63.6'%3E0%3C/text%3E%3Ctext x='38.5' y='63.6'%3E0%3C/text%3E%3Ctext x='41.5' y='61.6'%3E+%3C/text%3E%3Ctext x='44.5' y='63.6'%3E:%3C/text%3E%3Ctext x='51.5' y='63.6'%3E.%3C/text%3E%3Ctext x='6.5' y='67.6'%3E0%3C/text%3E%3Ctext x='16.5' y='69.6'%3E+%3C/text%3E%3Ctext x='21.5' y='71.6'%3E:%3C/text%3E%3Ctext x='28.5' y='69.6'%3E.%3C/text%3E%3Ctext x='37.5' y='67.6'%3E.%3C/text%3E%3Ctext x='47.5' y='69.6'%3E+%3C/text%3E%3Ctext x='51.5' y='71.6'%3E0%3C/text%3E%3Ctext x='54.5' y='67.6'%3E:%3C/text%3E%3Ctext x='15.5' y='77.6'%3E.%3C/text%3E%3Ctext x='26.5' y='77.6'%3E+%3C/text%3E%3Ctext x='28.5' y='73.6'%3E0%3C/text%3E%3Ctext x='41.5' y='75.6'%3E.%3C/text%3E%3Ctext x='53.5' y='75.6'%3E+%3C/text%3E%3Ctext x='7.5' y='83.6'%3E+%3C/text%3E%3Ctext x='15.5' y='83.6'%3E0%3C/text%3E%3Ctext x='16.5' y='83.6'%3E0%3C/text%3E%3Ctext x='31.5' y='81.6'%3E1%3C/text%3E%3Ctext x='40.5' y='83.6'%3E0%3C/text%3E%3Ctext x='1.5' y='89.6'%3E+%3C/text%3E%3Ctext x='14.5' y='89.6'%3E+%3C/text%3E%3Ctext x='18.5' y='89.6'%3E0%3C/text%3E%3Ctext x='20.5' y='87.6'%3E.%3C/text%3E%3Ctext x='26.5' y='85.6'%3E.%3C/text%3E%3Ctext x='28.5' y='85.6'%3E.%3C/text%3E%3Ctext x='46.5' y='87.6'%3E0%3C/text%3E%3Ctext x='49.5' y='85.6'%3E1%3C/text%3E%3Ctext x='32.5' y='93.6'%3E:%3C/text%3E%3Ctext x='37.5' y='95.6'%3E0%3C/text%3E%3Ctext x='1.5' y='97.6'%3E+%3C/text%3E%3Ctext x='8.5' y='99.6'%3E:%3C/text%3E%3Ctext x='18.5' y='97.6'%3E.%3C/text%3E%3Ctext x='26.5' y='97.6'%3E0%3C/text%3E%3Ctext x='28.5' y='99.6'%3E:%3C/text%3E%3Ctext x='34.5' y='99.6'%3E+%3C/text%3E%3Ctext x='45.5' y='97.6'%3E1%3C/text%3E%3Ctext x='52.5' y='97.6'%3E0%3C/text%3E%3Ctext x='5.5' y='103.6'%3E1%3C/text%3E%3Ctext x='20.5' y='107.6'%3E:%3C/text%3E%3Ctext x='25.5' y='107.6'%3E0%3C/text%3E%3Ctext x='38.5' y='107.6'%3E1%3C/text%3E%3Ctext x='48.5' y='107.6'%3E1%3C/text%3E%3Ctext x='18.5' y='113.6'%3E:%3C/text%3E%3Ctext x='2.5' y='117.6'%3E0%3C/text%3E%3Ctext x='10.5' y='115.6'%3E.%3C/text%3E%3Ctext x='21.5' y='115.6'%3E1%3C/text%3E%3Ctext x='9.5' y='125.6'%3E+%3C/text%3E%3Ctext x='38.5' y='121.6'%3E0%3C/text%3E%3C/g%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 56 126'%3E%3Cg fill='%23fff' font-family='monospace' font-size='1.76' text-anchor='middle'%3E%3Ctext x='6.5' y='5.6'%3E1%3C/text%3E%3Ctext x='18.5' y='1.6'%3E0%3C/text%3E%3Ctext x='25.5' y='1.6'%3E:%3C/text%3E%3Ctext x='7.5' y='9.6'%3E1%3C/text%3E%3Ctext x='8.5' y='11.6'%3E:%3C/text%3E%3Ctext x='17.5' y='11.6'%3E1%3C/text%3E%3Ctext x='20.5' y='7.6'%3E.%3C/text%3E%3Ctext x='24.5' y='7.6'%3E+%3C/text%3E%3Ctext x='38.5' y='11.6'%3E:%3C/text%3E%3Ctext x='42.5' y='11.6'%3E:%3C/text%3E%3Ctext x='50.5' y='9.6'%3E+%3C/text%3E%3Ctext x='52.5' y='11.6'%3E0%3C/text%3E%3Ctext x='12.5' y='15.6'%3E.%3C/text%3E%3Ctext x='27.5' y='17.6'%3E1%3C/text%3E%3Ctext x='28.5' y='15.6'%3E+%3C/text%3E%3Ctext x='32.5' y='17.6'%3E.%3C/text%3E%3Ctext x='41.5' y='13.6'%3E:%3C/text%3E%3Ctext x='0.5' y='23.6'%3E0%3C/text%3E%3Ctext x='11.5' y='23.6'%3E:%3C/text%3E%3Ctext x='13.5' y='21.6'%3E:%3C/text%3E%3Ctext x='28.5' y='19.6'%3E.%3C/text%3E%3Ctext x='41.5' y='21.6'%3E.%3C/text%3E%3Ctext x='44.5' y='21.6'%3E0%3C/text%3E%3Ctext x='49.5' y='19.6'%3E.%3C/text%3E%3Ctext x='3.5' y='27.6'%3E1%3C/text%3E%3Ctext x='16.5' y='27.6'%3E:%3C/text%3E%3Ctext x='28.5' y='25.6'%3E:%3C/text%3E%3Ctext x='4.5' y='35.6'%3E.%3C/text%3E%3Ctext x='15.5' y='33.6'%3E+%3C/text%3E%3Ctext x='16.5' y='33.6'%3E+%3C/text%3E%3Ctext x='44.5' y='31.6'%3E.%3C/text%3E%3Ctext x='5.5' y='37.6'%3E:%3C/text%3E%3Ctext x='26.5' y='41.6'%3E0%3C/text%3E%3Ctext x='28.5' y='41.6'%3E:%3C/text%3E%3Ctext x='45.5' y='39.6'%3E:%3C/text%3E%3Ctext x='1.5' y='45.6'%3E1%3C/text%3E%3Ctext x='7.5' y='43.6'%3E+%3C/text%3E%3Ctext x='16.5' y='43.6'%3E.%3C/text%3E%3Ctext x='22.5' y='43.6'%3E1%3C/text%3E%3Ctext x='41.5' y='45.6'%3E1%3C/text%3E%3Ctext x='16.5' y='49.6'%3E:%3C/text%3E%3Ctext x='24.5' y='49.6'%3E.%3C/text%3E%3Ctext x='31.5' y='51.6'%3E0%3C/text%3E%3Ctext x='32.5' y='53.6'%3E+%3C/text%3E%3Ctext x='39.5' y='51.6'%3E.%3C/text%3E%3Ctext x='55.5' y='53.6'%3E.%3C/text%3E%3Ctext x='12.5' y='57.6'%3E0%3C/text%3E%3Ctext x='16.5' y='57.6'%3E+%3C/text%3E%3Ctext x='20.5' y='57.6'%3E:%3C/text%3E%3Ctext x='24.5' y='55.6'%3E0%3C/text%3E%3Ctext x='35.5' y='57.6'%3E0%3C/text%3E%3Ctext x='49.5' y='55.6'%3E:%3C/text%3E%3Ctext x='6.5' y='65.6'%3E.%3C/text%3E%3Ctext x='8.5' y='63.6'%3E+%3C/text%3E%3Ctext x='13.5' y='61.6'%3E+%3C/text%3E%3Ctext x='18.5' y='63.6'%3E+%3C/text%3E%3Ctext x='20.5' y='63.6'%3E0%3C/text%3E%3Ctext x='38.5' y='63.6'%3E0%3C/text%3E%3Ctext x='41.5' y='61.6'%3E+%3C/text%3E%3Ctext x='44.5' y='63.6'%3E:%3C/text%3E%3Ctext x='51.5' y='63.6'%3E.%3C/text%3E%3Ctext x='6.5' y='67.6'%3E0%3C/text%3E%3Ctext x='16.5' y='69.6'%3E+%3C/text%3E%3Ctext x='21.5' y='71.6'%3E:%3C/text%3E%3Ctext x='28.5' y='69.6'%3E.%3C/text%3E%3Ctext x='37.5' y='67.6'%3E.%3C/text%3E%3Ctext x='47.5' y='69.6'%3E+%3C/text%3E%3Ctext x='51.5' y='71.6'%3E0%3C/text%3E%3Ctext x='54.5' y='67.6'%3E:%3C/text%3E%3Ctext x='15.5' y='77.6'%3E.%3C/text%3E%3Ctext x='26.5' y='77.6'%3E+%3C/text%3E%3Ctext x='28.5' y='73.6'%3E0%3C/text%3E%3Ctext x='41.5' y='75.6'%3E.%3C/text%3E%3Ctext x='53.5' y='75.6'%3E+%3C/text%3E%3Ctext x='7.5' y='83.6'%3E+%3C/text%3E%3Ctext x='15.5' y='83.6'%3E0%3C/text%3E%3Ctext x='16.5' y='83.6'%3E0%3C/text%3E%3Ctext x='31.5' y='81.6'%3E1%3C/text%3E%3Ctext x='40.5' y='83.6'%3E0%3C/text%3E%3Ctext x='1.5' y='89.6'%3E+%3C/text%3E%3Ctext x='14.5' y='89.6'%3E+%3C/text%3E%3Ctext x='18.5' y='89.6'%3E0%3C/text%3E%3Ctext x='20.5' y='87.6'%3E.%3C/text%3E%3Ctext x='26.5' y='85.6'%3E.%3C/text%3E%3Ctext x='28.5' y='85.6'%3E.%3C/text%3E%3Ctext x='46.5' y='87.6'%3E0%3C/text%3E%3Ctext x='49.5' y='85.6'%3E1%3C/text%3E%3Ctext x='32.5' y='93.6'%3E:%3C/text%3E%3Ctext x='37.5' y='95.6'%3E0%3C/text%3E%3Ctext x='1.5' y='97.6'%3E+%3C/text%3E%3Ctext x='8.5' y='99.6'%3E:%3C/text%3E%3Ctext x='18.5' y='97.6'%3E.%3C/text%3E%3Ctext x='26.5' y='97.6'%3E0%3C/text%3E%3Ctext x='28.5' y='99.6'%3E:%3C/text%3E%3Ctext x='34.5' y='99.6'%3E+%3C/text%3E%3Ctext x='45.5' y='97.6'%3E1%3C/text%3E%3Ctext x='52.5' y='97.6'%3E0%3C/text%3E%3Ctext x='5.5' y='103.6'%3E1%3C/text%3E%3Ctext x='20.5' y='107.6'%3E:%3C/text%3E%3Ctext x='25.5' y='107.6'%3E0%3C/text%3E%3Ctext x='38.5' y='107.6'%3E1%3C/text%3E%3Ctext x='48.5' y='107.6'%3E1%3C/text%3E%3Ctext x='18.5' y='113.6'%3E:%3C/text%3E%3Ctext x='2.5' y='117.6'%3E0%3C/text%3E%3Ctext x='10.5' y='115.6'%3E.%3C/text%3E%3Ctext x='21.5' y='115.6'%3E1%3C/text%3E%3Ctext x='9.5' y='125.6'%3E+%3C/text%3E%3Ctext x='38.5' y='121.6'%3E0%3C/text%3E%3C/g%3E%3C/svg%3E");
}

/* A row is a fixed fraction of the width, so a narrow viewport fits roughly
   twice as many of them into the band, and on top of that the copy runs edge
   to edge with none of the wide layout's empty margin for the field to sit
   in. Halving the tint keeps the perceived weight where the design put it
   rather than letting the texture crowd the paragraph. */
/* The band carries a lot of vertical padding for a wide layout. On a phone
   that is most of a screen spent before the first word, and another gap
   before the first section, so both come in. */
@media (max-width: 48rem) {
  /* Bigger cells put more of each glyph behind any given line, so the tint
     comes down to hold the same weight over the copy as the wide layout. */
  .hero::before { opacity: 0.10; }
  .hero::after { opacity: 0.16; }

  .hero {
    padding-top: calc(var(--step) * 6);
    padding-bottom: calc(var(--step) * 4);
  }
  main { padding-top: calc(var(--step) * 3); }
}

.brand-mark {
  display: inline-flex;
  align-items: center;
  gap: 0.6ch;
  margin: 0 0 calc(var(--step) * 4);
  font-weight: 700;
}
.brand-mark__chevron { width: 1.1em; height: 1.1em; flex: none; color: var(--muted); }
.brand-mark__type {
  display: inline-block;
  animation: reveal 700ms steps(10) 150ms both;
}
.brand-mark__cursor {
  display: inline-block;
  width: 0.5em;
  height: 1.1em;
  background: var(--accent);
  vertical-align: text-bottom;
  /* Runs forever, on the same keyframes as the wordmark's cursor. A terminal
     caret that stops after a few beats reads as a stalled animation rather
     than a live prompt, which is the opposite of what the brand mark is for.
     The delay lets the name finish typing before the caret appears.
     prefers-reduced-motion still pins it to a solid block below. */
  animation: blink 1000ms steps(1) 850ms infinite;
}

.hero-title {
  margin: 0 0 calc(var(--step) * 3);
  font-weight: 800;
  text-transform: uppercase;
  line-height: 0.92;
  letter-spacing: -0.01em;
  font-size: clamp(2.625rem, 8.4vw, 6.5rem);
}
.hero-title span { display: block; }

.hero-facts-wrap {
  border-top: 1px dashed var(--rule);
  padding-top: calc(var(--step) * 3);
}
/* Label and value are split by colour so the eye can scan the three
   categories without the values competing with them. */
.hero-facts {
  font-size: clamp(0.9375em, 1.3vw, 1.125em);
  color: var(--muted);
}
.hero-facts b { color: var(--ink); font-weight: 400; }

/* ============================================================
   Buttons, status, chips, section headers
   ============================================================ */

.btn {
  display: inline-block;
  padding: calc(var(--step) * 1.5) calc(var(--step) * 3);
  border: 1px solid var(--accent);
  background: var(--accent);
  color: var(--bg);
  font: inherit;
  text-decoration: none;
}
.btn:hover { opacity: 0.88; }

/* Laid out rather than left to inline flow: as inline-blocks the two buttons
   wrapped onto a second line with only the leading between them, so on a
   narrow screen they read as one stuck-together block. */
.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--step);
}

/* Below the width where all three fit on one line, the wrap goes from ragged
   to deliberate: the action that matters takes the full column and the two
   profiles split what is left, equally, so a six-letter label and an
   eight-letter one still line up. The breakpoint is where they stop fitting,
   not the layout breakpoint, so a tablet keeps the single row. */
@media (max-width: 32rem) {
  .hero-actions {
    display: grid;
    grid-template-columns: 1fr 1fr;
  }
  .hero-actions .btn { text-align: center; }
  .hero-actions .btn:first-child { grid-column: 1 / -1; }
}

.btn--ghost {
  background: transparent;
  color: var(--accent);
}

.status { white-space: nowrap; }
/* The glyph is decorative; the word next to it carries the meaning,
   so status never depends on color or shape alone. The empty alt text
   after the slash keeps the raw symbol out of the accessibility tree,
   so a screen reader reads "Live", not "black circle Live". */
.status::before { margin-inline-end: 0.5ch; }
.status--live::before { content: "\25CF" / ""; color: var(--accent); }
.status--beta::before { content: "\25D0" / ""; color: var(--muted); }
.status--planned::before { content: "\25CB" / ""; color: var(--muted); }
.status--dev::before { content: "\25D1" / ""; color: var(--muted); }

/* nowrap above is right for a card badge of one or two words and wrong for a
   sentence: at 320px the availability line ran 51px past the column and the
   hero's overflow:hidden clipped it silently, so scrollWidth reported nothing
   wrong. This lets it wrap, and hangs the marker the same way the fact list
   does so the second line starts under the text. */
.status--wrap {
  white-space: normal;
  padding-left: 1.5ch;
  text-indent: -1.5ch;
}

.chip {
  display: inline-block;
  padding: 0 0.75ch;
  border: 1px solid var(--rule);
  color: var(--muted);
  font-size: 0.875em;
}

.section { margin: 0 0 calc(var(--step) * 8); }

.section__title {
  display: flex;
  align-items: center;
  gap: 1ch;
  margin: 0 0 calc(var(--step) * 3);
  font-size: 1em;
  font-weight: 700;
  text-transform: lowercase;
  color: var(--muted);
}
/* Echoes the brand mark's prompt chevron at reading scale. The flex gap
   supplies the space after it, so the markup carries no filler entity. */
.section__title::before {
  content: ">";
  color: var(--accent);
}
/* Rule drawn as a flex-filling element, not as box-drawing characters, which
   break at fractional container widths. */
.section__title::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--rule);
}

/* ============================================================
   Project card and footer
   ============================================================ */

.cards { display: grid; gap: calc(var(--step) * 2); }

.card {
  border: 1px solid var(--rule);
  padding: calc(var(--step) * 3);
  transition: border-color 150ms ease;
}
.card:hover, .card:focus-within { border-color: var(--accent); }

.card__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 1ch;
}

/* A flex item's automatic minimum size is its longest unbreakable token,
   so wrapping alone does not stop a long domain from pushing the card
   past the viewport. These two make the wrap guarantee actually hold. */
.card__name { font-weight: 700; min-width: 0; overflow-wrap: anywhere; }
.card__name a { color: var(--ink); }

.card__desc { margin: calc(var(--step) * 2) 0; }

.card__stack { display: flex; flex-wrap: wrap; gap: 0.5ch; }

/* Repos are not products, so they get the same chevron treatment as the
   hero facts rather than a card that would overstate them. */
.oss {
  margin-top: calc(var(--step) * 3);
  padding-top: calc(var(--step) * 3);
  border-top: 1px dashed var(--rule);
}
.oss__title {
  margin: 0 0 var(--step);
  color: var(--muted);
  font-weight: 700;
  text-transform: lowercase;
}
.oss__links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--step);
  margin: 0 0 calc(var(--step) * 2);
}
.oss__link {
  display: inline-flex;
  align-items: center;
  gap: 0.6ch;
  padding: var(--step) calc(var(--step) * 2);
  border: 1px solid var(--rule);
  color: var(--ink);
  font-weight: 700;
  text-decoration: none;
}
.oss__link::before { content: ">"; color: var(--accent); font-weight: 400; }
.oss__link:hover, .oss__link:focus-visible { border-color: var(--accent); }
.oss__note { margin: 0; color: var(--muted); font-size: 0.875em; }

/* Sits outside <main>, since it is the page's footer and not the article's,
   so it has to repeat the reading column itself instead of inheriting it.
   Without this it ran the full width of the body and started a whole
   gutter to the left of every other line on the page. */
.legal {
  max-width: var(--col);
  margin: calc(var(--step) * 8) auto 0;
  padding-top: calc(var(--step) * 3);
  border-top: 1px solid var(--rule);
  color: var(--muted);
}
/* The type shrinks on the paragraphs rather than on the footer itself: --col
   is measured in ch, so a smaller font on the box would have quietly drawn a
   narrower column than the one every other block on the page sits in. */
.legal p { font-size: 0.875em; }
