/* ============================================================================
 *  chrome.css — THE FIXED TECHNICAL INTERFACE
 *  ---------------------------------------------------------------------------
 *  A control panel, not a navbar: hairline cell divisions, 10–11px labels, and
 *  no element large enough to compete with the stage behind it. It stays put
 *  through every scene and only changes its ink when the work universe turns
 *  the ground dark underneath it.
 * ========================================================================== */

.chrome {
  position: absolute;
  top: var(--edge);
  left: var(--edge);
  right: var(--edge);
  height: var(--chrome-h);
  z-index: 30;
  display: flex;
  align-items: stretch;
  color: var(--ink);
  font-family: var(--mono);
  transition: color var(--t-mid) linear;
}

.chrome__mark,
.chrome__id {
  display: none;
}

/* every direct child is a cell with a hairline on its right edge */
.chrome > * {
  display: flex;
  align-items: center;
  padding: 0 clamp(8px, 1vw, 16px);
  border-right: var(--hair) solid var(--ink-line);
  transition: border-color var(--t-mid) linear;
}
.chrome > *:last-child { border-right: 0; }

.chrome__mark {
  color: var(--ink-soft);
  text-decoration: none;
  border-right-color: var(--ink-soft);
  flex: 0 0 auto;
}

/* the wide empty span that makes the bar read as an instrument */
.chrome__statement {
  display: grid;
  grid-template-columns: auto auto auto 1fr;
  gap: clamp(8px, 1vw, 12px);
  align-items: center;
  min-width: 0;
  overflow: hidden;
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.chrome__statement span {
  display: inline-block;
  min-width: 0;
  white-space: nowrap;
}
/* THE NAME IS NOT SAID TWICE.
 *
 * The interface carries "Patrick LeRoy" at the top left, and the opening screen
 * carries it again as the wordmark — the same two words, one a small copy of
 * the other, on the same frame. The interface version is the one that has to
 * survive the whole page, so it is the one that waits: it is held back while
 * the hero is in view and arrives as the wordmark leaves. chrome.js sets
 * --id-in from the hero's own position. */
.chrome__statement-lead {
  opacity: calc(0.68 * var(--id-in, 1));
  transition: opacity 420ms var(--ease-out);
}
.chrome__statement-connector,
.chrome__statement-noun,
.chrome__statement-outcome {
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 320ms cubic-bezier(.22,.8,.2,1), transform 320ms cubic-bezier(.22,.8,.2,1);
}
.chrome__statement.is-visible .chrome__statement-connector,
.chrome__statement.is-visible .chrome__statement-noun,
.chrome__statement.is-visible .chrome__statement-outcome {
  opacity: 1;
  transform: translateY(0);
}
.chrome__statement-outcome {
  opacity: 0.82;
}

.chrome__nav {
  margin-left: auto;
  gap: clamp(14px, 2.2vw, 34px);
  flex: 0 0 auto;
}
.chrome__nav a {
  font-size: 11px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  text-decoration: none;
  padding: 4px 2px;
  position: relative;
}
.chrome__nav a::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: var(--hair);
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--t-fast) var(--ease-out);
}
.chrome__nav a:hover::after,
.chrome__nav a:focus-visible::after,
.chrome__nav a[aria-current="true"]::after { transform: scaleX(1); }
.chrome__nav a:hover,
.chrome__nav a:focus-visible,
.chrome__nav a[aria-current="true"] { color: var(--signal); }
.chrome__nav a { transition: color var(--t-fast) linear; }

.ctl {
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
  border: var(--hair) solid var(--ink-line);
  transition: background var(--t-fast) linear, border-color var(--t-fast) linear;
}
.ctl:hover { border-color: currentColor; }
.ctl[aria-pressed="true"] { background: var(--ink-soft); color: var(--field); border-color: var(--ink-soft); }

.chrome__aside {
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 2px;
  flex: 0 0 auto;
  font-family: var(--prose);
  font-size: clamp(11px, 1vw, 13px);
  font-style: italic;
  line-height: 1.25;
}
.chrome__aside a { text-underline-offset: 3px; }
.chrome__aside p:first-child {
  font-family: var(--mono);
  font-size: 8px;
  font-style: normal;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  opacity: 0.52;
}
.chrome__aside p:last-child {
  max-width: 31ch;
  white-space: nowrap;
}

/* ---- the loader holds the interface back until the hero reassembles ------ */
.is-booting .chrome > * { opacity: 0; transform: translateY(-6px); }
.chrome > * { transition: opacity 420ms var(--ease-out), transform 420ms var(--ease-out),
              border-color var(--t-mid) linear; }

/* ---- narrow ------------------------------------------------------------- */
@media (max-width: 1080px) {
  .chrome__aside { display: none; }
  .chrome__meta:last-child { display: none; }
}
@media (max-width: 720px) {
  .chrome__nav { gap: 14px; }
  .chrome__nav a { font-size: 10px; letter-spacing: 0.14em; }
  .chrome > * { padding: 0 8px; }

  /* THE ROTATING SENTENCE IS A DESKTOP AFFORDANCE. There is no room for
     "Patrick LeRoy <noun> that <outcome>" beside the nav on a 375px screen:
     it ran straight through the identity and under the links, so the header
     read "PATRICK LEWEBSITES THAT M". The identity stays; the reel does not —
     the statement section says the same thing at full size a screen later. */
  .chrome__statement-noun,
  .chrome__statement-connector,
  .chrome__statement-outcome { display: none; }

  .chrome__statement {
    grid-template-columns: auto;
    font-size: 9px;
    letter-spacing: 0.16em;
  }
}

/* ==========================================================================
 *  THE PROGRESS HAIRLINE
 *  --------------------------------------------------------------------------
 *  Twelve viewport-heights of scroll behind a fixed stage means the browser's
 *  own scrollbar is the only clue to position, and on a trackpad there isn't
 *  one. A single gold hairline across the top of the frame, filled to the
 *  timeline position, gives the page the sense of length it was missing.
 *  Decorative by design: `aria-hidden`, because the nav's current-section
 *  state is what carries the same information to assistive tech.
 * ======================================================================== */
.progress {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  z-index: 40;
  pointer-events: none;
  background: var(--ink-line-faint);
}

.progress i {
  display: block;
  height: 100%;
  width: 100%;
  transform: scaleX(var(--progress, 0));
  transform-origin: 0 50%;
  background: linear-gradient(90deg, var(--signal-deep), var(--signal));
  /* the fill chases the damped timeline, so it never jitters on a flick */
  will-change: transform;
}

/* it has no business being on screen during the loader's flat field */
.is-booting .progress { opacity: 0; }

/* ==========================================================================
 *  THE HEAD SCRIM
 *  --------------------------------------------------------------------------
 *  Sections overlap on purpose: one is still leaving as the next arrives, which
 *  is what stopped the frame going blank at every boundary. The cost is that
 *  outgoing type passes under the fixed interface on its way off the top, and
 *  a paragraph sliding through the nav reads as clutter rather than as motion.
 *
 *  Tuning the overlap number is the wrong lever — it trades one problem for the
 *  other. This is the fix that holds at any overlap: a short gradient of the
 *  ground colour pinned to the top edge, so anything travelling out of frame
 *  dissolves into the field just before it reaches the interface. It sits UNDER
 *  the chrome and OVER the stage, and it is invisible against the starfield
 *  because it is the same colour as the starfield's own ground.
 * ======================================================================== */
.head-scrim {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  /* Tall enough that display type is FULLY dissolved before it reaches the
     nav, not merely tinted. At the previous height a venture heading passing
     out of frame was still legible straight through the interface text. */
  height: calc(var(--chrome-h) + var(--edge) * 2 + 92px);
  z-index: 25;
  pointer-events: none;
  background: linear-gradient(
    180deg,
    var(--field-deep) 0%,
    var(--field-deep) 46%,
    rgba(5, 4, 3, 0.86) 66%,
    rgba(5, 4, 3, 0.48) 82%,
    transparent 100%
  );
}

/* the loader owns a flat field of its own; a second one on top of it just
   darkens the glyph */
.is-booting .head-scrim { opacity: 0; }

/* ---- THE IDENTITY MUST NOT BREAK AT 375px ------------------------------
   At narrow widths the statement grid collapses to a single column, which
   stacks its children — so "Patrick LeRoy" clipped to "PATRICK LER" and the
   connector "that" dropped onto a second line under it. The rotating parts
   were already meant to be hidden here; the connector was not in that list.
   The identity is protected, so it gets whatever room it needs and never
   wraps, never truncates. */
@media (max-width: 720px) {
  .chrome__statement {
    display: block;
    overflow: visible;
  }
  .chrome__statement-lead {
    display: block;
    white-space: nowrap;
    overflow: visible;
    font-size: 9px;
    letter-spacing: 0.14em;
  }
  /* every rotating part, including the connector that was missed */
  .chrome__statement-noun,
  .chrome__statement-connector,
  .chrome__statement-outcome,
  .chrome__statement-hidden {
    display: none !important;
  }
}
