

.fx-tag {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 500;
  line-height: 1.8;
  letter-spacing: -0.02em;
  text-transform: uppercase;
}

/* ---------------------------------------------------------- 1. the nav pill */

.fx-nav {
  position: fixed;
  top: var(--fx-edge);
  left: 50%;
  transform: translateX(-50%);
  z-index: 30;
  width: var(--fx-nav-w);
}

/* The band above the nav.

   The pill sits --fx-edge below the top of the screen, and in that gap the
   page arrived sharp — a headline scrolling up cut clean across the strip
   above the pill while the pill itself was frosted. This fills the gap with
   the same material, full width.

   It stops at the pill's bottom edge: run any deeper and it blurs copy that
   is nowhere near the header, which reads as fog over the page rather than as
   part of it.

   That hard stop is exactly why the mask is back. Full-bleed, a blur that
   ends on a line draws that line straight across the screen either side of
   the pill — the most visible thing on the page. Fading to nothing BY the
   pill's bottom edge, rather than past it, gets a soft ramp without putting
   any blur below the nav: the strip above the pill stays at full strength,
   and the falloff happens over the pill's own height, where the pill is
   covering it anyway. The ramp is a Tier B tell, allowlisted below — it
   paints no colour, it only says where this layer stops.

   z-index 29 puts it over the page sections (10) and under the pill and rail
   (30), so the pill stays crisp on top of its own band. */
.fx-scrim {
  position: fixed;
  inset: 0 0 auto 0;
  height: calc(var(--fx-edge) + var(--fx-nav-h));
  z-index: 29;
  pointer-events: none;
  /* Same fill as the pill, so the two read as one piece of glass — and where
     the backdrop layer is unsupported this alone still dims the strip. */
  background: rgba(9, 9, 10, 0.5);
}

/* language-flip-ok: the support probe for the frosted nav band. */
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .fx-scrim {
    /* language-flip-ok: frosted nav band, on an explicit product call. */
    -webkit-backdrop-filter: blur(18px) brightness(0.72);
    /* language-flip-ok: frosted nav band, on an explicit product call. */
    backdrop-filter: blur(18px) brightness(0.72);
    /* language-flip-ok: a mask stop, not a painted gradient. */
    -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 46%, transparent 100%);
    /* language-flip-ok: a mask stop, not a painted gradient. */
    mask-image: linear-gradient(to bottom, #000 0%, #000 46%, transparent 100%);
  }
}

/* The pill is frosted: what is behind it — the ASCII field, the hero headline,
   the problem copy once the page has scrolled under it — is blurred and
   darkened rather than covered.

   Tuned so the frost is actually VISIBLE. The first pass ran a 72% fill over
   brightness(0.55), which leaves the backdrop 15% of its original luminance —
   enough to read through the 60px hero headline and nothing else, so on body
   copy the pill was indistinguishable from the opaque plate it replaced. At
   50% over brightness(0.72) the backdrop keeps 36%, which reads as glass on
   ordinary text while still dimming it well clear of the label. The blur went
   to 18px for the same reason: the softness is what says "overlay" when the
   thing behind is too dark to show much of itself.

   This IS glassmorphism, which DESIGN.md §8 bans and which was deliberately
   stripped from this exact component (home.css §2 records the removal).
   Re-added on an explicit product call, 2026-08-26. The markers below are the
   documented Tier B allowlist — the same contract PR #330 used — and without
   them verify-language.sh blocks release tags on the backdrop properties. */
.fx-surface {
  position: relative;
  border-radius: var(--fx-radius);
  /* The opaque plate stays the DEFAULT, and the frost is opted into below.
     Written the other way round — translucent here, opaque inside a
     `@supports not (...)` — a browser that mis-evaluates the negated query
     lands on a translucent panel with the page showing through it sharp and
     undimmed, which is worse than never frosting at all. */
  background: var(--fx-raised);
  box-shadow: inset 0 0 0 1px var(--fx-border-soft);
  overflow: hidden;
  transition: border-radius var(--fx-dur) var(--fx-ease);
}

/* language-flip-ok: the support probe for the frosted nav. */
/* THE PILL DOES NOT FROST. It used to, and that second blur is what made the
   header shimmer.

   The scrim above already frosts this exact strip, and the pill sits INSIDE
   it — so the pill's backdrop was not the page, it was the scrim's own output:
   a blurred, masked, half-transparent layer that is itself re-sampling an
   animating canvas every frame. Two dependent backdrop passes over moving
   content, with a mask between them, is the configuration compositors are
   worst at; the two layers resolve on their own schedules and the disagreement
   is visible as a shimmer along the band.

   It also double-darkened. brightness(0.72) applied twice is 0.52, which is
   why the pill always sat heavier than the strip it lives in.

   So the pill keeps the opaque plate that was already its default (see
   `.fx-surface` above, where the comment notes the opaque form is deliberate),
   and the frost stays where one layer can own it. The band still reads as
   glass; the pill reads as a solid object standing on it, which is what it is. */
.fx-pill {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  height: var(--fx-nav-h);
  padding-inline: 14px;
}

.fx-pill__mark {
  display: flex;
  align-items: center;
  flex: 0 0 auto;
}
.fx-pill__mark img {
  height: 32px;
  width: auto;
}

/* The centre label scrambles once on load (see the reveal script). The sizer
   copy holds the final width so the scramble can't reflow the pill. */
.fx-reveal {
  position: relative;
  overflow: hidden;
  flex: 1 1 auto;
  text-align: center;
}
.fx-reveal-live {
  position: absolute;
  inset-inline: 0;
  top: 0;
  color: var(--fx-smoke);
}
/* The backer's name is the only part that changes, and the only part in
   colour — "Backed by" stays quiet in front of it. */
.fx-backer {
  color: var(--fx-orange);
}
.fx-reveal-sizer {
  opacity: 0;
  pointer-events: none;
}

/* The hero's calls, arriving in the menu.

   Desktop only, and on a deliberate condition: the page must never show two
   Downloads at once. While the hero is on screen its own row is the place to
   press. Below 900px `.fx-actions` already carries these at every scroll
   position, so the whole mechanism is scoped inside the media query rather
   than hidden by one.

   The pill itself does not change — the buttons live in the drawer, which is
   where a menu's actions belong and where there is room for them without the
   header growing under the reader. */
.fx-drawer__calls {
  display: none;
}

@media (min-width: 901px) {
  .fx-nav[data-past="true"] .fx-drawer__calls {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    gap: var(--s-2);
    /* The menu rows run edge to edge and end on a hairline; the buttons need
       air off that line or they read as a sixth row. */
    padding: var(--fx-space-md);
  }

  /* Matching the menu rows they sit under, not the hero's row: this is a
     menu, and a button taller than the row above it reads as a banner. */
  .fx-drawer__calls .fx-btn {
    height: 44px;
    border-radius: var(--fx-radius-lg);
  }
}

/* Their burger, verbatim: three equal 16x2 bars, 3px apart, drawn in
   currentColor. Opening does NOT rotate them into an X — the outer two
   translate 5px inward and land exactly on the middle one, so the icon
   collapses from three lines to one. */
.fx-burger {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 3px;
  /* 44x44 hit area, icon unchanged: the bars stay right-aligned inside it and
     the button is the last flex item, so widening it grows leftward into the
     pill's dead space rather than moving the icon. */
  width: 44px;
  height: 44px;
  padding: 0;
  background: none;
  border: 0;
  color: var(--fx-off-white);
  flex: 0 0 auto;
}
.fx-bar {
  display: block;
  width: 16px;
  height: 2px;
  margin-left: auto;
  background: currentColor;
  transition:
    transform 0.4s var(--fx-ease-inout),
    opacity 0.2s linear;
}
[data-open="true"] .fx-bar-top {
  transform: translateY(5px);
}
[data-open="true"] .fx-bar-bottom {
  transform: translateY(-5px);
}

/* --- the drawer ----------------------------------------------------------- */

/* Collapsed to a zero-height grid row; opening animates to 1fr, so the panel
   grows out of the pill instead of appearing under it. */
.fx-drawer {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--fx-dur) var(--fx-ease);
}
.fx-nav[data-open="true"] .fx-drawer {
  grid-template-rows: 1fr;
}
.fx-drawer > div {
  overflow: hidden;
  min-height: 0;
  /* The collapsed row hides the links visually but 0fr + overflow leave them
     in the tab order and the accessibility tree — the first Tab press on the
     page landed on five invisible links. visibility takes them out of both;
     the delay lets the close animation finish before they vanish. */
  visibility: hidden;
  transition: visibility 0s var(--fx-dur);
}
.fx-nav[data-open="true"] .fx-drawer > div {
  visibility: visible;
  transition-delay: 0s;
}

.fx-menu-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--fx-space-md);
  width: 100%;
  padding: var(--fx-space-md) 26px; /* theirs, verbatim */
  border-top: 1px solid var(--fx-line);
  color: var(--fx-off-white);
  text-align: left;
  opacity: 0;
  transform: translateY(-6px);
  transition:
    opacity 0.34s var(--fx-ease),
    transform 0.34s var(--fx-ease),
    background 0.2s linear;
}
.fx-nav[data-open="true"] .fx-menu-row {
  opacity: 1;
  transform: none;
  transition-delay: calc(50ms + var(--fx-i) * 45ms); /* their stagger, kept */
}
.fx-menu-row:hover {
  background: rgba(244, 242, 238, 0.04);
}

/* The drawer's motion lives in this file, so its reduced-motion rules do too —
   the essay pages load chrome.css without home.css, and a preference honored
   only on the home page is not honored. */
@media (prefers-reduced-motion: reduce) {
  .fx-drawer,
  .fx-drawer > div,
  .fx-menu-row,
  .fx-bar {
    transition: none;
  }
  .fx-nav[data-open="true"] .fx-menu-row {
    transition-delay: 0s;
  }
}

/* The skip link, shared by every page that carries this chrome. styles.css
   has its own copy for the pages that load it; same behavior, fx tokens. */
.skip {
  position: absolute; left: -9999px; top: 0;
  background: var(--fx-off-white); color: var(--fx-black);
  padding: 8px 16px; border-radius: 4px; z-index: 100;
}
.skip:focus { left: 16px; top: 16px; }

/* THE PAGES THAT CAME BEFORE THE CHROME. The landing page, /about and the
   essays each reserve their own room under the pill, because each has a
   different first block. The pages that were written without a nav at all —
   pricing, help, security, the 404s, the troubleshooting tree — have no such
   room, and the pill is fixed, so their first line arrived underneath it.
   One class on <body> gives them the clearance without touching a layout
   that was correct before the nav landed on it. */
body.fx-chrome-page main {
  padding-top: calc(var(--fx-edge) + var(--fx-nav-h) + 40px);
}

/* Anchor landings (#beta from llms.txt and old links; #definition from the
   essay skip links) must clear the floating pill, or the target arrives
   underneath it. */
#beta, #definition, #mechanism {
  scroll-margin-top: calc(var(--fx-edge) + var(--fx-nav-h) + 16px);
}

.fx-menu-label {
  font-size: clamp(20px, 1.9vw, 28px);
  font-weight: 400;
  line-height: 1.15;
  letter-spacing: -0.02em;
}
.fx-menu-row .fx-tag {
  color: var(--fx-ash);
}

/* The drawer's actions are the narrow-screen stand-in. Above 900px the home
   page's hero is already showing the same two calls on the foot of the first
   screen, so opening the drawer there would put Download and Book a call on
   one screen twice. Pages with no hero of their own turn this row back on —
   see the `.fx-actions { display: flex }` line in their own sheet. */
.fx-actions {
  display: none;
  flex-direction: column;
  gap: 4px;
  padding: 10px;
  border-top: 1px solid var(--fx-line);
}
@media (max-width: 900px) {
  .fx-actions {
    display: flex;
  }
}
.fx-actions .fx-btn {
  height: 58px;
  border-radius: var(--fx-radius-lg);
}

.fx-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  height: var(--fx-nav-h);
  padding-inline: 18px;
  border-radius: var(--fx-radius);
  white-space: nowrap;
  font-size: 14px;
  font-weight: 500;
  transition:
    background 0.28s var(--fx-ease),
    color 0.28s var(--fx-ease),
    box-shadow 0.28s var(--fx-ease);
}
.fx-btn-primary {
  background: var(--fx-off-white);
  color: var(--fx-black);
}
.fx-btn-primary:hover {
  background: #ffffff;
  color: var(--fx-black);
}
.fx-btn-outline {
  color: var(--fx-off-white);
  box-shadow: inset 0 0 0 1px var(--fx-line);
}
.fx-btn-outline:hover {
  color: var(--fx-off-white);
  box-shadow: inset 0 0 0 1px rgba(244, 242, 238, 0.32);
}

/* The individual essays style a bare `a` warm and underline it on hover —
   that is a rule for body copy. The chrome opts out of both. */
.fx-nav a,
.fx-nav a:hover,
.site-foot a,
.site-foot a:hover {
  text-decoration: none;
}

/* ---------------------------------------------------------- the site footer */

/* Both ends sit on the same bottom line: the copyright is one line, the links
   are a stacked column, so aligning to the end is what puts them in opposite
   bottom corners rather than centring the short side. The element selector is
   never used, so an essay page's own `footer {}` rule cannot reach it — every
   property that rule sets is restated here. */
.site-foot {
  flex: 0 0 auto;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s-4) var(--fx-space-lg);
  /* Full width, so the two ends reach the page's own corners rather than the
     content column's — the padding is what holds them off the edge. */
  margin: 0;
  padding: var(--fx-space-lg) var(--fx-edge) var(--fx-edge);
  border-top: 0;
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.6;
  letter-spacing: -0.02em;
  color: var(--fx-ash);
}
.site-foot__links {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
  text-align: right;
}

/* The copyright reads at the same weight as the links, not a step below. */
.site-foot__copy { color: var(--fx-smoke); }
.site-foot a { color: var(--fx-smoke); }
.site-foot a:hover { color: var(--fx-off-white); text-decoration: none; }

/* ---------------------------------------------------------- OS-adaptive CTA */

/* The <html class="os-windows"> flag picks which download variant is shown.
   home.css repeats this block at its own end, after the rail's `display`
   declarations — at equal specificity the later rule has to win, or both
   variants render in the rail. */
.dl-win {
  display: none;
}
.os-windows .dl-mac {
  display: none;
}
.os-windows .dl-win {
  display: flex;
}

/* ---------------------------------------------------------- essay cards */

/* The same three cards run on the landing page's essays strip and on the
   essays index, so the grid and the card live here rather than in either
   page's own sheet. */

.page-eyebrow {
  margin: 0 0 var(--s-10);
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  color: var(--fx-smoke);
}

/* Three across, collapsing to two and then one. minmax(0,1fr) rather than
   1fr so a long title cannot push a column wider than its share. */
.essays {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s-16) var(--s-8);
}
@media (max-width: 1000px) { .essays { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 680px)  { .essays { grid-template-columns: minmax(0, 1fr); gap: var(--s-12); } }

.card { display: block; color: inherit; }

/* The cover is typographic on purpose: there is no cover art in the repo,
   and inventing some would put generated imagery in a load-bearing slot.
   Real art can drop straight in here — same box, same ratio. */
/* No padding or flex any more: both were there to seat the kicker at the
   cover's foot, and the kicker is gone. The wireframe fills the box. */
.card__cover {
  position: relative;
  display: block;
  aspect-ratio: 4 / 3;
  border: 1px solid var(--fx-border-soft);
  border-radius: var(--fx-radius);
  background: var(--fx-raised);
  transition: border-color 200ms var(--fx-ease), background 200ms var(--fx-ease);
}
/* Orange on hover, the same ring the session panel takes — one colour across
   the site meaning "this one is live under your pointer". */
.card:hover .card__cover { border-color: var(--fx-orange); background: var(--fx-dark); }

/* The wireframe sits behind the kicker and fills the cover. */
.card__wire {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}

.card__title {
  margin: var(--s-5) 0 0;
  font-size: 21px;
  line-height: 1.25;
  font-weight: 500;
  letter-spacing: -0.018em;
  color: var(--fx-off-white);
  text-wrap: pretty;
}
.card:hover .card__title { color: #ffffff; }

.card__excerpt {
  margin: var(--s-3) 0 0;
  font-size: 15px;
  line-height: 1.55;
  color: var(--fx-smoke);
  text-wrap: pretty;
}

.card__meta {
  margin: var(--s-5) 0 0;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: -0.02em;
  color: var(--fx-ash);
}
