/* ============================================================================
   BRAVAIS — shared chrome
   One source of truth for the nav, brand mark, pills, cards and surfaces, so
   index / team / pitch actually match instead of being eyeballed three times.

   THEMED (light + dark). The raw brand tokens below (--ink, --lum, --steel …)
   are FIXED brand constants — they never change. Theme-varying colour comes
   from the SEMANTIC layer (--bg, --text, --surface, --mark …), which remaps
   under :root[data-theme="light"]. Rules use the semantic tokens so both
   themes fall out of one set of declarations. The active theme is stamped on
   <html data-theme> by the inline theme-init script (no FOUC) and flipped by
   the toggle in theme.js.
   ============================================================================ */

:root {
  --ink:      #07090B;
  --navy:     #0F1622;
  --graphite: #11151D;
  --chrome:   #2A3242;
  /* #4A5260 scored 2.53:1 on --ink — fails AA at any size, and it was the colour of every
     9–11px mono caption AND of two controls. Raised to #767E8C (4.88:1 on --ink), then again
     to #868E9C, which is the raise that matters: --smoke was only ever measured against --ink,
     but these captions sit on CARD SURFACES and on the ambient video bed, which are lighter.
     On the live site the partner-card captions measured 4.44:1 there — under AA. #868E9C
     carries 30% more luminance and clears it. The original survives as --smoke-rule for
     hairlines, where contrast is moot. */
  --smoke:      #868E9C;
  --smoke-rule: #4A5260;
  --silver:   #8C93A0;
  --steel:    #B6BCC6;
  --lum:      #E8EEF8;

  --rule:     rgba(255,255,255,0.07);
  --rule-mid: rgba(255,255,255,0.13);
  --surface:  rgba(17,21,29,0.72);
  --surface-hi: rgba(26,36,52,0.78);

  --font-sans: 'Geist', -apple-system, 'Helvetica Neue', sans-serif;
  --font-mono: 'Geist Mono', 'JetBrains Mono', ui-monospace, monospace;

  /* the index's rounding language — pills for controls, soft radius for panels */
  --r-pill:  999px;
  --r-panel: 14px;
  --r-card:  12px;

  --b-mark: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 120'%3E%3Cg fill='%23fff'%3E%3Cpath d='M24 18 H70 A16 16 0 0 1 70 50 H24 Z'/%3E%3Cpath d='M24 62 H75 A21 21 0 0 1 75 104 H24 Z'/%3E%3C/g%3E%3C/svg%3E");
}

/* ============================================================================
   THEME MODEL — the VIDEO defines dark vs light, not the chrome
   The ambient bed video swaps to its living-daylight twin on brv:themechange; the
   shared chrome (nav, cards, copy) stays the SAME dark-glass in both modes. It reads
   perfectly over either bed, and its dark scrim is what keeps copy legible over the
   bright light footage. So there is deliberately no token flip here — do not add one.
   ============================================================================ */

/* ---------- skip link ----------
   index.html has one; the subpages did not, so a keyboard user had to Tab through the brand and
   four nav pills on every visit before reaching a word of content. Hidden until focused, so it
   costs the visual design nothing. Every page that uses this must give its <main> an id the link
   can target, and main must be focusable (tabindex="-1") or the jump moves the viewport without
   moving focus — which is the classic broken skip link. */
.bx-skip {
  position: fixed; top: 10px; left: 10px; z-index: 999;
  transform: translateY(-160%);
  padding: 12px 20px; border-radius: var(--r-pill, 999px);
  background: var(--lum); color: var(--ink);
  font-family: var(--font-mono); font-size: 11px; letter-spacing: .16em;
  text-transform: uppercase; text-decoration: none;
  transition: transform .18s ease;
}
.bx-skip:focus { transform: translateY(0); }
/* the landing target must not draw a ring just for being jumped to */
main:focus { outline: none; }

/* ---------- focus ----------
   No focus style was authored anywhere on the site. Nothing SUPPRESSED one either — there is
   no `outline: none` in the codebase, which is the usual sin — so keyboard users fell back to
   whatever ring the browser draws by default, over near-black glass. State it explicitly, in
   the brand's own light. :focus-visible, so clicking a button with a mouse leaves no ring. */
:focus-visible {
  outline: 2px solid var(--lum);
  outline-offset: 3px;
  border-radius: 2px;
}

/* ---------- top bar ---------- */
.bx-topbar {
  position: fixed; top: 0; left: 0; right: 0; z-index: 60;
  display: flex; align-items: center; justify-content: space-between;
  /* Matched EXACTLY to the engine's .sw-topbar (scrub-engine.js:592), which builds the bar on
     index.html. The pill tokens were already reconciled between the two — same background,
     radius, padding, type size — but the BAR was not: this used to be `16px clamp(18px,4vw,40px)`
     against the engine's clamp(14px,2.4vw,26px) / clamp(18px,5vw,64px), making the bar 75px tall
     here and 95px on the homepage. The brand mark and the nav pill jumped 20px up and 24px left
     the moment you clicked through from index. Two builders, one bar — they have to agree. */
  gap: 16px; padding: clamp(14px, 2.4vw, 26px) clamp(18px, 5vw, 64px);
  padding-top: calc(clamp(14px, 2.4vw, 26px) + env(safe-area-inset-top, 0px));
  pointer-events: none;
}
.bx-topbar > * { pointer-events: auto; }

.bx-brand { display: flex; align-items: center; gap: 10px; text-decoration: none; color: var(--lum); }
.bx-brand__mark {
  width: 22px; height: 22px; background: var(--lum);
  -webkit-mask: var(--b-mark) center/contain no-repeat;
          mask: var(--b-mark) center/contain no-repeat;
}
.bx-brand__name {
  font-family: var(--font-mono); font-size: .82rem;
  letter-spacing: .20em; text-transform: uppercase;
}

/* the pill group — identical to the index's section nav */
.bx-nav {
  display: flex; gap: 4px; padding: 5px;
  background: rgba(17,21,29,0.55);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  border: 1px solid var(--rule);
  border-radius: var(--r-pill);
}
.bx-nav a, .bx-nav button {
  font: inherit; font-family: var(--font-sans); font-size: .82rem; font-weight: 300;
  color: rgba(232,238,248,0.55);
  text-decoration: none; border: 0; background: transparent; cursor: pointer;
  padding: 7px 14px; border-radius: var(--r-pill); white-space: nowrap;
  transition: color .25s, background .25s;
}
.bx-nav a:hover, .bx-nav button:hover { color: var(--lum); background: rgba(232,238,248,0.06); }
.bx-nav a.is-active, .bx-nav button.is-active { color: var(--ink); background: var(--steel); }

/* divider between in-page sections and cross-page links */
.bx-nav .bx-nav__sep {
  width: 1px; align-self: stretch; margin: 4px 4px;
  background: var(--rule-mid); flex: 0 0 1px;
}

/* ---------- surfaces ---------- */
.bx-panel {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-panel);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
}
.bx-card {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-card);
  transition: background .25s, border-color .25s, transform .25s;
}
.bx-card:hover {
  background: var(--surface-hi);
  border-color: var(--rule-mid);
  transform: translateY(-2px);
}

/* ---------- buttons ---------- */
.bx-btn {
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--font-sans); font-size: .9rem; font-weight: 400;
  padding: 10px 20px; border-radius: var(--r-pill);
  border: 1px solid var(--rule-mid); background: transparent;
  color: var(--lum); text-decoration: none; cursor: pointer;
  transition: transform .2s, background .2s, border-color .2s;
}
.bx-btn:hover { transform: translateY(-2px); }
.bx-btn--primary { background: var(--lum); color: var(--ink); border-color: var(--lum); }

/* ---------- type helpers ---------- */
.bx-eyebrow {
  font-family: var(--font-mono); font-size: 10px; letter-spacing: .28em;
  text-transform: uppercase; color: var(--silver);
}
.bx-mono-k {
  font-family: var(--font-mono); font-size: 9px; letter-spacing: .24em;
  text-transform: uppercase; color: var(--silver);
}

/* ---------- ambient bed (team / pitch) ---------- */
.bx-bed { position: fixed; inset: 0; z-index: 0; overflow: hidden; background: var(--ink); }
.bx-bed video {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  min-width: 100%; min-height: 100%; object-fit: cover;
  /* opacity AND filter ease on the same .7s clock so saturation never snaps mid-cross-fade.
     .7s is the site-wide theme-dissolve duration (descent + all beds). */
  opacity: 0; filter: saturate(.5); transition: opacity .7s ease, filter .7s ease;
}
.bx-bed video.on { opacity: .40; }
.bx-bed::after {
  content: ""; position: absolute; inset: 0; transition: opacity .7s ease;
  background:
    linear-gradient(180deg, rgba(7,9,11,.92) 0%, rgba(7,9,11,.52) 34%, rgba(7,9,11,.84) 100%),
    radial-gradient(72% 62% at 50% 45%, transparent, rgba(7,9,11,.62));
}
/* Light mode: the bed is a LIVING daylight clip — lift its opacity + saturation so it reads bright,
   and lighten the scrim a touch; the scrim stays dark enough to keep the copy legible. */
:root[data-theme="light"] .bx-bed video { filter: saturate(.92); }
:root[data-theme="light"] .bx-bed video.on { opacity: .56; }
/* lighten the scrim by easing its OPACITY down (transitionable) rather than swapping the gradient
   (which would snap) — so the scrim brightens on the same .7s clock as everything else. */
:root[data-theme="light"] .bx-bed::after { opacity: .78; }
@media (prefers-reduced-motion: reduce) {
  .bx-bed video { display: none; }
  /* Hover lifts and the burger's icon morph are motion too — hold them still. Color/background
     transitions are kept: they are not motion. */
  .bx-card, .bx-btn { transition: background .25s, border-color .25s; }
  .bx-card:hover, .bx-btn:hover { transform: none; }
  .bx-burger span, .bx-burger span::before, .bx-burger span::after { transition: none; }
  .bx-sheet { transition: none; }
}

/* ---------- mobile nav ----------
   Below 860px the pill row is too wide to sit honestly next to the brand, so it
   is replaced by a burger + full-screen sheet — the same pattern index.html
   uses, so the three pages behave identically on a phone.
   Markup is built by chrome.js from the .bx-nav links already on the page. */
.bx-burger { display: none; }

/* chrome.js appends the sheet to <body> on EVERY viewport, but every rule that styles it
   used to live inside the 860px query below. Above 860px it therefore had no styling at
   all and rendered as a bare <nav> of unstyled anchors — default hyperlink blue — in normal
   flow at the foot of the page, merely painted over by the fixed background layer. It also
   put eight invisible controls into the tab order. Hide it by default; the query turns it on. */
.bx-sheet { display: none; }

@media (max-width: 860px) {
  .bx-nav { display: none; }

  /* The burger sits INSIDE .bx-topbar, which has its own z-index (60) and so
     creates a stacking context — the burger's z-index is trapped inside it and
     the sheet (300) paints over the whole bar, burying the close button. Lift
     the bar above the sheet so the X stays tappable while the menu is open. */
  .bx-topbar { z-index: 310; }

  .bx-burger {
    display: inline-flex; align-items: center; justify-content: center;
    width: 42px; height: 42px; padding: 0;
    border: 1px solid var(--rule); border-radius: var(--r-pill);
    background: rgba(17,21,29,0.55); -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
    cursor: pointer;
  }
  .bx-burger span {
    display: block; position: relative; width: 16px; height: 1px;
    background: var(--lum); transition: background .2s;
  }
  .bx-burger span::before,
  .bx-burger span::after {
    content: ""; position: absolute; left: 0; width: 16px; height: 1px;
    background: var(--lum); transition: transform .25s ease;
  }
  .bx-burger span::before { top: -5px; }
  .bx-burger span::after  { top:  5px; }
  .bx-burger.is-open span { background: transparent; }
  .bx-burger.is-open span::before { transform: translateY(5px) rotate(45deg); }
  .bx-burger.is-open span::after  { transform: translateY(-5px) rotate(-45deg); }

  .bx-sheet {
    position: fixed; inset: 0; z-index: 300;   /* above the pitch deck stage */
    display: flex; flex-direction: column; justify-content: center; gap: 2px;
    padding: 0 clamp(22px,7vw,48px);
    padding-bottom: env(safe-area-inset-bottom, 0px);
    background: rgba(7,9,11,0.94); -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px);
    /* visibility keeps the CLOSED sheet's links out of the keyboard tab order —
       pointer-events blocks clicks but not Tab, so focus was landing on four
       invisible full-screen links (the same bug the display:none above fixes
       for desktop). The 0s/.3s delay hides it only after the fade completes. */
    opacity: 0; pointer-events: none; visibility: hidden;
    transition: opacity .3s ease, visibility 0s linear .3s;
  }
  .bx-sheet.is-open { opacity: 1; pointer-events: auto; visibility: visible; transition-delay: 0s; }
  .bx-sheet a {
    display: flex; align-items: baseline; gap: 14px;
    font-family: var(--font-sans); font-weight: 300; font-size: 1.5rem;
    color: var(--lum); text-decoration: none;
    border-bottom: 1px solid var(--rule); padding: 18px 2px;
  }
  .bx-sheet a.is-active { color: var(--steel); }
  .bx-sheet a:last-child { border-bottom: 0; }
  .bx-sheet .bx-sheet__n {
    font-family: var(--font-mono); font-size: 10px; letter-spacing: .22em;
    color: var(--smoke); flex: 0 0 auto;
  }
}

@media (max-width: 720px) {
  .bx-brand__name { display: none; }
}
