/* Nav bar: small logo left, hamburger right, at every screen size.
   The owner chose hamburger-only, so the panel header names the current place
   and the command palette is the keyboard path. DESIGN.md sections 5 and 9.2. */

@layer components {
  .nav {
    position: sticky;
    top: 0;
    z-index: var(--z-popover);
    /* `min-height`, not `height`. With `box-sizing: border-box` a fixed 64px
       swallows the safe-area inset rather than clearing it, so on a notched
       phone the bar had 17px of usable height and the 44px hamburger overflowed
       it. The bar now grows by the inset instead. `--nav-height` stays the
       content height, which is what `calc(100dvh - var(--nav-height))` in
       features/landing, features/auth and features/story-editor means by it. */
    min-height: var(--nav-height);
    padding-inline: var(--space-4);
    padding-top: env(safe-area-inset-top, 0);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    /* The bar states its own ground rather than reading `--surface-1`, and
       the direction of the dependency is the point: Noval defines
       `--surface-1` AS this value, because the owner picked this bar as the
       reference for every translucent surface in the product (2026-09-11).
       So on the default skin the bar and the cards are the same glass.

       Reading the token instead would have been tidier and wrong. The bar is
       a floating surface on every skin, while `--surface-1` is whatever that
       skin wants a CARD to be - and Holo wants flat opaque panels with no
       blur at all. Pointing the bar at the card token turned Holo's bar
       solid, which is a change to a skin nobody asked about.

       If this value changes, change `--surface-1` in
       `styles/skins/skin-noval/skin-noval.css` with it. Each says so. */
    background: color-mix(in oklab, var(--bg) 78%, transparent);
    backdrop-filter: blur(14px);
    border-bottom: 1px solid var(--border);
  }

  /* The shell exists so the advanced panel can be a SIBLING of the bar while
     still being mounted by this component. `display: contents` keeps both as
     layout children of #app, which is what lets the bar stay sticky at 0 and
     the panel sticky under it. */
  .nav-shell { display: contents; }

  /* Empty on every route that is not universe-scoped, and an empty flex child
     with `flex: 1` would still claim the row. Collapsed instead, so the bar on
     the landing page is exactly what it was. */
  .nav__universe:empty { display: none; }

  .nav__universe {
    display: flex;
    align-items: center;
    min-width: 0;
    flex: 1 1 auto;
    /* The bar never scrolls sideways (DESIGN.md section 5). Whatever the
       trail cannot fit, it ellipsises. */
    overflow: hidden;
  }

  /* The two halves of the trail: the universe crumb, then the story and
     chapter controls on a chapter route. Each is its own host because the
     components that fill them call `replaceChildren` on what they are given. */
  .nav__universe > div {
    display: flex;
    align-items: center;
    min-width: 0;
  }

  .nav__universe > div:empty { display: none; }

  .nav__brand {
    font-family: var(--font-display);
    font-size: var(--text-lg);
    letter-spacing: var(--brand-tracking);
    text-decoration: none;
    padding: var(--space-2);
    margin-inline-start: calc(var(--space-2) * -1);
    border-radius: var(--radius-sm);
    display: inline-flex;
    align-items: center;
  }

  /* THE MARK ON A PHONE, THE WORD ON EVERYTHING ELSE (owner, 2026-09-24).
     "SUPERNOVAL" is twice the width "NOVAL" was, and the nav bar is a single
     row that also has to hold the universe crumb and its chevron - at 390px
     the word was taking a third of the bar before the crumb had said anything.

     THE MARK KEEPS ITS OWN COLOUR, which is the one place this file does not
     follow the skin, and it is deliberate. `.brand-title` under the default
     skin paints the wordmark as a gradient clipped to the text and sets
     `color: transparent` to do it - so a mark drawn with `currentColor`, or
     masked and filled with it, renders invisible there. It is also a brand
     asset rather than an interface element: the same file is already the
     favicon. The skin's `filter: drop-shadow(...)` still reaches it, so it
     picks up the wordmark's glow without inheriting its fill.

     Mobile-first, matching the `min-width: 640px` this file already uses for
     the menu, so there is one breakpoint in the nav rather than two. */
  .nav__brand-mark {
    block-size: 1.6rem;
    inline-size: auto;
  }

  .nav__brand-word { display: none; }

  @media (min-width: 640px) {
    .nav__brand-mark { display: none; }
    .nav__brand-word { display: inline; }
  }
  .nav__brand:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }

  /* ── THE RAIL (v2, 2026-10-02) ────────────────────────────────────────
     The destinations as bare mono words. No pills, no boxes, no underline -
     spacing and letter-tracking do the work, after the owner's reference
     sites. It REPLACES the hamburger above 760px rather than sitting beside
     it: the first attempt showed both and the owner correctly called that
     redundant, so there is exactly one way to reach a place at each width. */
  .nav__rail { display: none; }

  @media (min-width: 760px) {
    .nav__rail {
      display: flex;
      align-items: center;
      gap: clamp(1rem, 2vw, 2.25rem);
      margin-inline-start: auto;
    }
    /* THE BURGER STAYS, AND IT IS NOT THE REDUNDANCY THE OWNER REJECTED.
     *
     * It was hidden here at first, and that quietly broke the product: the
     * rail carries the DESTINATIONS, and everything after the menu's first
     * separator - Contact, About and SIGN OUT - lives only in the sheet. With
     * the burger gone above 760px there was no way to sign out on a desktop
     * at all. `navigation.spec.js` caught it as a click timing out on a
     * control that was not there.
     *
     * So the split is by KIND rather than by width, which is what stops it
     * being duplication: the rail is the places you go, the sheet is your
     * account and the pages about the product. Nothing appears in both -
     * `renderItems` cuts the same list at the same separator for each. */
    .nav .nav__burger { display: grid; }

    /* The other half of that split: above 760px the sheet drops the items the
       rail is already showing. One place for each destination, at every
       width - which is the thing the first attempt got wrong. */
    .nav__menu .nav__item[data-tier="primary"] { display: none; }
  }

  /* One item. The owner's chosen hover, transcribed from the markup they
     sent: a blurred dot slides in from the left and sharpens as it arrives,
     the whole label shifts right, and the word rolls up while a second copy
     rolls in behind it. */
  .nav__rail-item {
    /* `position: relative` and the 400ms come from `.bracketed` in the kit. */
    display: inline-flex;
    align-items: center;
    gap: calc(8px * var(--ui-scale));
    padding-inline: var(--space-1);
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--text-muted);
    text-decoration: none;
    white-space: nowrap;
    transition: color var(--roll-dur) var(--ease-out);
  }

  .nav__rail-item:hover,
  .nav__rail-item:focus-visible { color: var(--text); }
  .nav__rail-item:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 4px; }
  .nav__rail-item[aria-current="page"] { color: var(--text); }

  /* THE BRACKETS AND THE ROLL MOVED TO `styles/kit.css` (2026-10-05).

     Home's hero tabs asked for this exact hover by name - owner: "tabs should
     have same on hover animations as the nav-bar buttons" - and kit.css's own
     rule for a second consumer is to add its class to the list rather than
     write a second copy. The rail now wears `.bracketed` and `.roll` from the
     kit, declared in `nav.js`, and what is left here is only what is
     genuinely the NAV's: this item's type, tracking and colour.

     `--nav-roll` went with them; the kit's token is `--roll-dur` and carries
     the same 400ms default. */

  .nav__burger {
    width: calc(44px * var(--ui-scale));
    height: calc(44px * var(--ui-scale));
    display: grid;
    place-content: center;
    gap: 5px;
    border-radius: var(--radius-sm);
    cursor: pointer;
    background: none;
    border: 0;
  }
  .nav__burger:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }

  .nav__bar {
    display: block;
    width: 20px;
    height: 2px;
    background: var(--text);
    border-radius: 2px;
    transition: transform var(--dur-3) var(--ease-out),
                opacity var(--dur-2) var(--ease-out);
  }

  .nav__burger[aria-expanded="true"] .nav__bar:nth-child(1) {
    transform: translateY(7px) rotate(45deg);
  }
  .nav__burger[aria-expanded="true"] .nav__bar:nth-child(2) { opacity: 0; }
  .nav__burger[aria-expanded="true"] .nav__bar:nth-child(3) {
    transform: translateY(-7px) rotate(-45deg);
  }

  /* Mobile first, which is also what DESIGN.md section 8 asks for: "Menu is a
     full-width sheet" on mobile, "a 280px anchored card" on desktop. It was
     the 280px card at every width, which at 390 left a 16px sliver of the page
     showing down one side and read as a misplaced popover rather than as a
     sheet. */
  .nav__menu {
    position: fixed;
    inset-block-start: calc(var(--nav-height) + env(safe-area-inset-top, 0));
    inset-inline: 0;
    inset-block-end: auto;
    max-height: calc(100dvh - var(--nav-height) - env(safe-area-inset-top, 0));
    overflow-y: auto;
    overscroll-behavior: contain;
    z-index: var(--z-overlay);
    background: var(--surface-3);
    backdrop-filter: var(--glass-filter-strong);
    border-block-end: 1px solid var(--border);
    box-shadow: var(--shadow-2);
    padding: var(--space-2) var(--space-2) max(var(--space-2), env(safe-area-inset-bottom, 0));
    display: grid;
    gap: 2px;
    align-content: start;
    transform-origin: top center;
    animation: menu-in var(--dur-3) var(--ease-out) both;
  }
  .nav__menu[hidden] { display: none; }

  @media (min-width: 640px) {
    .nav__menu {
      inset-block-start: calc(var(--nav-height) + env(safe-area-inset-top, 0) + var(--space-2));
      inset-inline-start: auto;
      inset-inline-end: var(--space-4);
      width: min(300px, calc(100vw - var(--space-8)));
      max-height: calc(100dvh - var(--nav-height) - var(--space-6));
      border: 1px solid var(--border);
      /* SQUARE (2026-10-05). The sheet was the last floating surface still
         drawn at `--radius-md` after the kit went square, which is most of
         why the owner said it "doesnt match new style anymore". */
      border-radius: 0;
      padding: var(--space-2);
      transform-origin: top right;
    }
  }

  @keyframes menu-in {
    from { opacity: 0; transform: translateY(calc(var(--motion, 1) * -8px)); }
    to { opacity: 1; transform: none; }
  }

  /* "You are here", built from the kit's label row - the same hairline-beside-
     a-word the page's own bands wear. The border-bottom it used to carry is
     gone: the rule in the label row IS that line now, and drawing both put
     two horizontals within 20px of each other. */
  .nav__place {
    display: grid;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3) var(--space-4);
  }

  /* `.nav__place-label` takes its type from `styles/kit.css`'s label list;
     only the rule's reach is this component's business. */

  .nav__place-name {
    font-family: var(--font-display);
    font-size: var(--text-lg);
    line-height: var(--text-lg-lh);
    font-weight: 300;
    letter-spacing: -0.01em;
    color: var(--text);
    overflow-wrap: anywhere;
  }

  .nav__item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    width: 100%;
    min-height: calc(44px * var(--ui-scale));
    padding: var(--space-2) var(--space-3);
    border-radius: 0;
    background: none;
    border: 0;
    /* THE RAIL'S VOICE, at a sheet's size (owner, 2026-10-05: the menu should
       "re-use elements and components so it looks and feels cohesive"). Mono,
       uppercase and tracked exactly as `.nav__rail-item` is, and faint until
       you are on it or over it - so the two halves of the navigation read as
       one set of words rather than as a bar and a dropdown. */
    color: var(--text-faint);
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    letter-spacing: 0.16em;
    text-transform: uppercase;
    transition: color var(--roll-dur) var(--ease-out);
    text-align: start;
    text-decoration: none;
    cursor: pointer;
    animation: item-in var(--dur-2) var(--ease-out) both;
    animation-delay: calc(var(--i, 0) * 24ms);
  }
  /* NO FILL ON HOVER. A row that lights up a grey block is the pattern the
     rest of this product stopped using when the buttons went outlined - the
     ink moves, and the roll underneath does the rest. */
  .nav__item:hover,
  .nav__item:focus-visible { color: var(--text); background: none; }
  .nav__item:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: -2px; }

  /* How many messages are waiting. The one place in this menu that spends the
     accent, because it is the one thing here that is NEWS rather than a
     destination - and it only exists when the number is above zero, so a menu
     with nothing waiting is unchanged. The item is already
     `justify-content: space-between`, so this needs no placement of its own. */
  .nav__badge {
    flex: 0 0 auto;
    min-inline-size: 1.25rem;
    padding: 0 var(--space-1);
    border-radius: var(--radius-pill, 999px);
    background: var(--accent);
    color: var(--text-on-accent);
    font-size: var(--text-xs);
    line-height: 1.25rem;
    font-weight: 700;
    text-align: center;
    font-variant-numeric: tabular-nums;
  }

  /* The current destination. Colour, weight and a leading bar, so the marker
     survives a monochrome display and a glance. The bar is drawn rather than
     added as padding so the label does not shift between states.

     Heads up when you read this: the rule is correct and today it never
     matches. `nav.js` sets `aria-current` inside an `effect()` that reads
     `currentRoute()`, which is a plain getter and not a signal, so the effect
     runs once and never again. The same file already solves this for the
     "You are here" header by listening for EV.NAVIGATE. Snippet R3-A. */
  .nav__item[aria-current="page"] {
    color: var(--accent);
    position: relative;
  }
  .nav__item[aria-current="page"]::before {
    content: "";
    position: absolute;
    inset-inline-start: 0;
    inset-block: var(--space-2);
    inline-size: 2px;
    background: var(--accent);
  }

  @keyframes item-in {
    from { opacity: 0; transform: translateX(calc(var(--motion, 1) * 6px)); }
    to { opacity: 1; transform: none; }
  }

  .nav__sep {
    height: 1px;
    background: var(--divider);
    margin: var(--space-3) var(--space-3);
  }

  /* The foot is a label row like the head, so the sheet opens and closes on
     the same device. Its own rule replaces the border it used to draw. */
  .nav__hint {
    padding: var(--space-2) var(--space-3) var(--space-1);
    margin-block-start: var(--space-2);
  }

  @media (prefers-reduced-motion: reduce) {
    .nav__menu, .nav__item { animation: none; }
    .nav__bar { transition: none; }
  }
}
