/* =============================================================
   Sprawl — shared boot choreography for non-homepage pages.

   The homepage (index.html) has a richer, tree-specific boot
   sequence inlined in its own <style>. Every other page loads
   this file instead. It covers:

     1. Site-wide colour palette (kept in sync with the homepage's
        inline :root / html.dark). Each page has its own :root inline
        but this file loads AFTER those <style> blocks, so these
        declarations override and the palette stays centralised.
     2. Topbar bottom rule sweeps in left→right.
     3. Topbar title / nav groups fade in in a small left-to-right
        stagger (same groups every page).
     4. Any element tagged with `.boot-item` + inline `--boot-index`
        fades in on cue. The sprawl-boot.js helper `sprawlBoot.stagger`
        tags + indexes the direct children of a container in one call.
     5. Chip-style hover effect shared by topbar nav + .ctl buttons.

   `body.boot` is present on <body> from page render; sprawl-boot.js
   strips it after ~3.5s, so late-rendering content or later
   re-renders (scroll-to-load-more, etc.) simply appear instantly.
   ============================================================= */

/* --- Colour palette ------------------------------------------------ */

:root {
  --fg:   #171718;       /* primary text + structural lines */
  --bg:   #e0e2e1;       /* page background */
  --mute: #c31a1a;       /* secondary text + non-active tree elements */
  --hl:   #202020;       /* highlighted / active — hover chips, selected cells */
  --tr:   #343535;       /* tree's non-active stroke */
  --sel-bg: rgba(0, 0, 0, 0.06);   /* hover tint on non-selected cells */
}

html.dark {
  --fg:   #e0e2e1;
  --bg:   #171717;
  --mute: #c22d2d;
  --hl:   #a2a2a2;
  --tr:   #b4b4b4;
  --sel-bg: rgba(255, 255, 255, 0.12);
}

@keyframes boot-drawH  { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes boot-fadeIn { from { opacity: 0; }          to { opacity: 1; } }

/* Replace the page's topbar border with a ::after overlay so the rule
   can animate in. `!important` is needed because each page declares
   `border-bottom: var(--rule) solid var(--fg)` on its own .topbar rule
   inline, and specificity/order would otherwise beat this file. */
.topbar { border-bottom: 0 !important; }
.topbar::after {
  content: "";
  position: absolute;
  bottom: 0; left: 0; right: 0;
  height: var(--rule, 1px);
  background: var(--fg);
}
body.boot .topbar::after {
  transform: scaleX(0);
  transform-origin: left center;
  animation: boot-drawH 0.5s ease-out forwards;
}

/* Topbar groups fade in roughly left-to-right. Each page shares the
   same nav-group class names (nav-middle, nav-feed, …), so this
   selector list works unmodified everywhere. */
body.boot .topbar > .title,
body.boot .topbar > .title-group,
body.boot .topbar > .nav-middle,
body.boot .topbar > .nav-feed,
body.boot .topbar > .nav-marketplace,
body.boot .topbar > .nav-right {
  opacity: 0;
  animation: boot-fadeIn 0.4s ease-out forwards;
}
body.boot .topbar > .title,
body.boot .topbar > .title-group     { animation-delay: 0.2s;  }
body.boot .topbar > .nav-middle      { animation-delay: 0.3s;  }
body.boot .topbar > .nav-feed        { animation-delay: 0.35s; }
body.boot .topbar > .nav-marketplace { animation-delay: 0.4s;  }
body.boot .topbar > .nav-right       { animation-delay: 0.45s; }

/* Per-item progressive reveal. Pages tag items with .boot-item +
   --boot-index via the helper in sprawl-boot.js. Items fade in in
   index order, 35ms apart, offset 0.3s so they follow the topbar. */
body.boot .boot-item {
  opacity: 0;
  animation: boot-fadeIn 0.4s ease-out calc(var(--boot-index, 0) * 35ms + 0.3s) forwards;
}

/* "loading…" placeholders each page ships in its initial HTML are
   suppressed while boot is active — the progressive reveal would
   otherwise briefly flash the word before the real content lands.
   If the fetch genuinely outlives the boot window, the rule stops
   matching at 3.5s and the placeholder becomes visible, so the
   reader still gets feedback on a slow network. */
body.boot .boot-loading { opacity: 0; }

/* --- Topbar nav + .ctl chip-hover ---------------------------------------
   Topbar labels (SPRAWL, FEED, AUTHORS, ENTITIES, ARCS, MARKETPLACE,
   ABOUT, SKILL, CONNECT, DARK) default to --mute. On hover they lift
   to a solid --hl background with --bg text — the "chip" effect the
   homepage uses. Padding + equal negative margin keep neighbouring
   items from shifting when the chip appears. The default a:hover
   underline still applies, so destination links read as both chip
   AND link.
   .ctl (HIDE INFO, EXPAND, RESET, RANDOM, etc.) uses the same chip
   treatment without the underline — they're actions, not links. */
/* SPRAWL title sits quieter in --mute; every other nav label (FEED,
   AUTHORS, ENTITIES, ARCS, MARKETPLACE, ABOUT, SKILL, CONNECT, DARK)
   reads in --fg so the navigation itself feels part of the content. */
.topbar .title { color: var(--mute); }
.topbar nav a  { color: var(--fg); }
.topbar .title:hover,
.topbar nav a:hover {
  background: var(--hl);
  color: var(--bg);
  padding: 2px 6px;
  margin: -2px -6px;
}

.ctl { cursor: pointer; user-select: none; color: var(--mute); }
.ctl:hover {
  text-decoration: none;
  background: var(--hl);
  color: var(--bg);
  padding: 2px 6px;
  margin: -2px -6px;
}

/* =============================================================
   Mobile hamburger + dropdown nav.

   Shared by every non-homepage page. (index.html carries an
   identical copy inline because its <style> is monolithic.)

   Desktop (>720px): hamburger hidden, normal topbar rendered.
   Mobile (≤720px):  all desktop nav groups hidden, hamburger
                     visible; clicking it toggles .is-open on
                     #nav-mobile which flips it to display: flex.
   ============================================================= */

.nav-hamburger {
  /* !important because Safari's <button> UA style otherwise leaks
     through in edge cases (empty buttons with only absolute-positioned
     children were rendering as a full-width grid item). */
  display: none !important;
  background: transparent;
  border: 0;
  padding: 0;
  margin: 0;
  cursor: pointer;
  justify-self: end;
  width: 22px;
  height: 16px;
  position: relative;
}
.nav-hamburger > span {
  position: absolute;
  left: 0;
  right: 0;
  height: var(--rule, 1px);
  background: var(--fg);
  transition: transform 160ms ease, opacity 120ms ease, top 160ms ease;
}
.nav-hamburger > span:nth-child(1) { top: 0; }
.nav-hamburger > span:nth-child(2) { top: 50%; transform: translateY(-50%); }
.nav-hamburger > span:nth-child(3) { top: calc(100% - var(--rule, 1px)); }
.nav-hamburger.is-open > span:nth-child(1) { top: 50%; transform: translateY(-50%) rotate(45deg); }
.nav-hamburger.is-open > span:nth-child(2) { opacity: 0; }
.nav-hamburger.is-open > span:nth-child(3) { top: 50%; transform: translateY(-50%) rotate(-45deg); }

.nav-mobile {
  display: none;
  position: fixed;
  top: var(--topbar-h, 44px);
  left: 0;
  right: 0;
  background: var(--bg);
  flex-direction: column;
  gap: 14px;
  padding: 18px var(--pad, 12px);
  border-bottom: var(--rule, 1px) solid var(--fg);
  z-index: 19;
  letter-spacing: 0.04em;
}
.nav-mobile.is-open { display: flex; }
.nav-mobile a { display: block; padding: 2px 0; }

@media (max-width: 720px) {
  .topbar { grid-template-columns: 1fr auto; }
  .topbar .title-group { gap: 12px; }
  .topbar .stats { font-size: 12px; }

  .topbar > .nav-middle,
  .topbar > .nav-feed,
  .topbar > .nav-marketplace,
  .topbar > .nav-right { display: none; }

  .nav-hamburger { display: inline-block !important; }
}
