/* Navbar — restored to the locked structure (CLAUDE.md §2):
   nav items LEFT · logo CENTRE · two round store buttons RIGHT. Fixed, light. */
.navbar {
  position: fixed;
  isolation: isolate;
  top: 0; left: 0; right: 0;
  z-index: 40;
  height: var(--nav-h);
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  padding-inline: var(--gutter);
  color: var(--hero-ink);
  /* No background and no blur: the copy fades out as it reaches the bar
     instead (see paintFades in hero-timeline.js), so nothing needs hiding. */
}

.navbar__nav { display: flex; gap: var(--sp-8); font-size: calc(var(--fs-sm) + 2px); }
/* Text-only version of the button hover: the character roll, no background. */
.navbar__nav a {
  color: var(--hero-ink);
  opacity: 0.72;
  transition: opacity 0.25s ease, color 0.3s ease;
}
.navbar__nav a:hover { opacity: 1; }
/* Current section */
.navbar__nav a[aria-current="true"] { color: var(--brand); opacity: 1; }

/* While the About panel is behind the bar, the whole width under the navbar is
   brand orange — and the two things that are themselves orange (the active nav
   link and the logo mark) disappear into it. Both go white for the duration.
   The class is toggled from JS; see initNavOverArt(). */
/* Navbar tint ------------------------------------------------------------
   Over most of the page the bar has no background and the copy fades as it
   passes behind it. Three sections are different: their ground is a flat
   colour, and plain copy scrolling under an invisible bar is noisy there.

   The bar takes THAT SECTION'S OWN colour and dissolves downward into it, so
   there is no edge anywhere — the navbar text gets a clean ground without the
   bar reading as a separate panel. Same approach as .legal-scrim in legal.css,
   which fades the pixels in a band rather than drawing a box over them.

   The gradient lives on ::after, taller than the bar itself (--nav-h + 40px):
   a background is clipped to its own box, so fading inside a 72px navbar would
   be abrupt. Opacity is what transitions — background-image cannot.

   The zero stops are written as rgba of the same colour, NOT `transparent`.
   `transparent` is rgba(0,0,0,0), and interpolating toward it can pull a grey
   cast through the middle of the fade. Same reason .legal-scrim spells its out.

   Set by initNavTint() in dom/hover-roll.js, landing page only. */
.navbar { background-color: transparent; }

.navbar::after {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: calc(var(--nav-h) + var(--sp-10));
  z-index: -1;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.3s ease;
}
.navbar[data-nav-tint]::after { opacity: 1; }

.navbar[data-nav-tint="white"]::after {
  background-image: linear-gradient(
    var(--bg-2) 0%, var(--bg-2) 46%, rgba(255, 255, 255, 0) 100%);
}
.navbar[data-nav-tint="bg3"]::after {
  background-image: linear-gradient(
    var(--bg-3) 0%, var(--bg-3) 46%, rgba(247, 246, 245, 0) 100%);
}
/* the footer carries the hero gradient; this is its colour at the top */
.navbar[data-nav-tint="grad"]::after {
  background-image: linear-gradient(
    var(--hero-grad-b) 0%, var(--hero-grad-b) 46%, rgba(255, 238, 229, 0) 100%);
}

/* Over the About artwork the mark is inverted to white — a light ground behind
   it would erase it, so no scrim is drawn there. */
.navbar--on-art::after { opacity: 0 !important; }

@media (prefers-reduced-motion: reduce) {
  .navbar::after { transition: none; }
}

.navbar--on-art .navbar__nav a[aria-current="true"] { color: var(--secondary); }
.navbar--on-art .navbar__panel a[aria-current="true"] { color: var(--secondary); }
/* The mark ships as solid orange paths inside an <img>, so `fill` cannot reach
   it — inverting is the only way to turn it white. */
.navbar--on-art .navbar__mark { filter: brightness(0) invert(1); }
/* Both transition, so leaving the orange settles back rather than snapping. */
.navbar__nav a[aria-current="true"],
.navbar__panel a[aria-current="true"] { transition: color 0.3s ease; }
.navbar__mark { transition: filter 0.3s ease; }

.navbar__logo { display: flex; align-items: center; gap: var(--sp-2); justify-self: center; }
.navbar__mark { height: calc((var(--sp-6) + 2px) * 1.2); width: auto; }
.navbar__word { height: calc((var(--sp-4) + 2px) * 1.2); width: auto; }

.navbar__stores { display: flex; gap: var(--sp-2); justify-self: end; }

/* Round icon button — light surface */
.icon-btn {
  display: grid; place-items: center;
  width: var(--sp-10); height: var(--sp-10);
  border-radius: 999px;
  border: 1px solid var(--hero-hair);
  background: var(--hero-card);
  transition: background 0.25s, border-color 0.25s;
}
.icon-btn:hover { background: rgba(255, 255, 255, 0.85); border-color: rgba(26, 26, 26, 0.26); }
/* The navbar's pair are solid, not the translucent card fill — they sit over
   the artwork and the phone, where a see-through pill reads as unfinished. */
.navbar__stores .icon-btn { background: var(--secondary); }
.navbar__stores .icon-btn:hover { background: var(--secondary); border-color: rgba(26, 26, 26, 0.26); }
.icon-btn img { width: var(--sp-4); height: var(--sp-4); opacity: 0.85; }

/* The store glyphs and the wordmark ship as solid black paths, so on the dark
   theme they have to be inverted to read at all. The logo MARK is brand orange
   and works on both, so it is deliberately left alone. */
:root[data-theme="dark"] .icon-btn img { filter: brightness(0) invert(1); opacity: 0.92; }
/* The navbar sits over the top of the beam — the buttons need a fill of their
   own or the white glyphs vanish into it. */
:root[data-theme="dark"] .icon-btn {
  background: rgba(6, 7, 12, 0.55);
  border-color: rgba(244, 247, 255, 0.22);
}
:root[data-theme="dark"] .navbar__word { filter: brightness(0) invert(1); }
:root[data-theme="dark"] .icon-btn:hover { background: rgba(244, 247, 255, 0.16); }

/* Between 768 and 1023 the +2px nav runs into the centred logo — tighten the
   gap and drop back to the base size so all three groups still fit. */
@media (min-width: 768px) and (max-width: 1023px) {
  .navbar__nav { gap: var(--sp-4); font-size: var(--fs-sm); padding-right: var(--sp-6); }
}

/* ---- Mobile menu ------------------------------------------------------
   Below 768 the inline nav is hidden, so it needs a way back: a hamburger in
   the navbar opening a panel underneath it. */
.navbar__toggle { display: none; }
.navbar__panel { display: none; }

@media (max-width: 767px) {
  /* toggle LEFT, then the logo, stores on the right. 24px either side. */
  .navbar {
    grid-template-columns: auto 1fr auto;
    column-gap: var(--sp-4);
    padding-inline: 24px;
  }
  .navbar__nav { display: none; }
  /* grid-row is required as well as grid-column: the toggle comes AFTER the
     logo in the DOM but sits in an earlier column, and sparse auto-placement
     answers that by starting a new row — which stacked the navbar in two. */
  .navbar__toggle { grid-column: 1; grid-row: 1; justify-self: start; }
  .navbar__logo   { grid-column: 2; grid-row: 1; justify-self: start; }
  .navbar__stores { grid-column: 3; grid-row: 1; justify-self: end; }

  .navbar__toggle {
    display: grid;
    gap: 5px;
    width: var(--sp-6);
    cursor: pointer;
    padding: var(--sp-2) 0;
    /* above the drawer, so the close (x) is always reachable — the panel is
       positioned and would otherwise paint over this */
    position: relative;
    z-index: 2;
  }
  .navbar__toggle span {
    display: block;
    height: 1.5px;
    width: var(--sp-6);
    background: var(--hero-ink);
    border-radius: 2px;
    transition: transform 0.4s cubic-bezier(0.22, 1, 0.36, 1);
  }
  .navbar[data-open="true"] .navbar__toggle span:nth-child(1) { transform: translateY(3.25px) rotate(45deg); }
  .navbar[data-open="true"] .navbar__toggle span:nth-child(2) { transform: translateY(-3.25px) rotate(-45deg); }

  /* Side drawer, in from the LEFT. */
  .navbar__panel {
    display: block;
    position: fixed;
    z-index: 1;
    top: 0;
    left: 0;
    width: min(78vw, 320px);
    height: 100svh;
    padding-top: calc(var(--nav-h) + var(--sp-6));
    background: var(--bg);
    transform: translateX(-100%);
    /* A CLOSED PANEL MUST PAINT NOTHING ON SCREEN.
       The shadow used to be declared here unconditionally, and translateX(-100%)
       does NOT take a shadow off screen with the box: 18px 0 50px is offset 18px
       to the RIGHT with a 50px blur, so it spilled from x=0 to roughly x=68 at
       up to 16% black, full height. That is the faint vertical band down the
       left edge — below 768px only, because this panel exists nowhere else, and
       on every page, because the navbar is lifted into all of them by
       tools-pages.py and tools-legal.py.
       The border had the same fault in miniature: width min(78vw, 320px)
       resolves to 292.5px at 375, and the resulting half-pixel translate can
       leave the hairline straddling x=0.
       Both now belong to the open state, and both transition with the slide so
       neither pops in. */
    box-shadow: 18px 0 50px rgba(26, 26, 26, 0);
    border-right: 1px solid transparent;
    transition:
      transform 0.45s cubic-bezier(0.22, 1, 0.36, 1),
      box-shadow 0.45s cubic-bezier(0.22, 1, 0.36, 1),
      border-color 0.45s cubic-bezier(0.22, 1, 0.36, 1);
    overflow-y: auto;
  }
  .navbar[data-open="true"] .navbar__panel {
    transform: translateX(0);
    box-shadow: 18px 0 50px rgba(26, 26, 26, 0.16);
    border-right-color: var(--hero-hair);
  }

  .navbar__panel-inner { display: flex; flex-direction: column; }
  .navbar__panel a {
    font-family: var(--font-head);
    font-size: var(--fs-lg);
    color: var(--text);
    padding: var(--sp-4) 24px;
    border-bottom: 1px solid rgba(26, 26, 26, 0.08);
  }
  .navbar__panel a:last-child { border-bottom: 0; }
  .navbar__panel a[aria-current="true"] { color: var(--brand); }
}
