/* =========================================================================
   Image Collections & Scrollytelling — styles
   Palette: bg #060606 · borders #27272a · text #f4f4f5 · accent sky-400 #38bdf8
   Per-collection accent is injected inline as --accent / --accent-rgb.
   ========================================================================= */

:root {
  --bg: #060606;
  --bg-2: #0c0c0e;
  --panel: rgba(24, 24, 27, 0.55);
  --panel-solid: #131316;
  --border: #27272a;
  --border-soft: rgba(63, 63, 70, 0.4);
  --text: #f4f4f5;
  --text-2: #d4d4d8;
  --text-3: #a1a1aa;
  --text-4: #71717a;
  --accent: #38bdf8;
  --accent-rgb: 56, 189, 248;
  --topbar-h: 60px;
  --font-display: "Space Grotesk", system-ui, sans-serif;
  --font-body: "Inter", system-ui, sans-serif;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html { scroll-behavior: smooth; }

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  line-height: 1.5;
}

a { color: inherit; text-decoration: none; }
.mono { font-family: ui-monospace, "SF Mono", Menlo, monospace; color: var(--text-3); }

/* ---- Top progress rail -------------------------------------------------- */
.progress-rail {
  position: fixed; top: 0; left: 0; right: 0;
  height: 3px; z-index: 60;
  background: rgba(255, 255, 255, 0.04);
}
.progress-fill {
  height: 100%; width: 0%;
  background: linear-gradient(90deg, #38bdf8, #a78bfa, #34d399);
  box-shadow: 0 0 12px rgba(56, 189, 248, 0.6);
  transition: width 0.08s linear;
}

/* ---- Top bar ------------------------------------------------------------ */
/* Flush to y=0 (the progress rail overlays its top edge rather than sitting
   above it) so the studio selector lands on exactly the same pixel here, on the
   meme wall, and in the storefront. */
.topbar {
  position: fixed; top: 0; left: 0; right: 0; z-index: 50;
  height: var(--topbar-h);
  display: flex; align-items: center; gap: 1.2rem;
  padding: 0 clamp(0.9rem, 3vw, 2rem);
  background: rgba(6, 6, 6, 0.72);
  backdrop-filter: blur(14px) saturate(140%);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  border-bottom: 1px solid var(--border-soft);
}
.brand { display: flex; align-items: center; gap: 0.6rem; flex-shrink: 0; }
.brand-glyph {
  width: 18px; height: 18px; border-radius: 5px;
  background: conic-gradient(from 140deg, #38bdf8, #a78bfa, #34d399, #38bdf8);
  box-shadow: 0 0 14px rgba(56, 189, 248, 0.5);
}
.brand-text { font-family: var(--font-display); font-weight: 700; letter-spacing: -0.01em; font-size: 1rem; }
.brand-dim { color: var(--text-4); font-weight: 500; margin-left: 0.15rem; }

.hint-btn {
  flex-shrink: 0; font-family: var(--font-display);
  font-size: 0.72rem; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--text-4); background: none; border: 0; cursor: pointer;
  padding-left: 0.5rem;
}
.hint-btn:hover { color: var(--accent); }

/* ---- Collection nav (all widths) ---------------------------------------- */
/* ‹ · current collection ▾ · › — one control instead of the old chip-per-
   collection row, which outgrew the topbar once the library passed a dozen
   collections. On desktop it sits inline at the right of row 1; on a phone the
   topbar wraps and it takes a full-width second row (see the media query). */
.colnav {
  display: flex; align-items: center; gap: 0.4rem;
  margin-left: auto; flex: 0 1 340px; min-width: 0;
}
.colnav-arrow {
  flex: 0 0 auto;
  width: 36px; height: 36px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--border); border-radius: 10px;
  background: rgba(24, 24, 27, 0.6); color: var(--text-2);
  font-size: 1.25rem; line-height: 1; cursor: pointer;
}
.colnav-arrow:hover:not(:disabled) { color: var(--text); border-color: var(--text-4); }
.colnav-arrow:disabled { opacity: 0.35; cursor: default; }
.colnav-pill {
  flex: 1 1 auto; min-width: 0;
  display: inline-flex; align-items: center; gap: 0.5rem;
  height: 36px; padding: 0 0.85rem;
  border: 1px solid var(--border); border-radius: 999px;
  background: rgba(24, 24, 27, 0.6); color: var(--text);
  font-family: var(--font-body); font-size: 0.86rem; font-weight: 600;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}
.colnav-pill:hover,
.colnav-pill[aria-expanded="true"] {
  border-color: rgba(var(--chip-rgb, 56, 189, 248), 0.55);
  background: rgba(var(--chip-rgb, 56, 189, 248), 0.12);
}
.colnav-dot {
  flex: 0 0 auto; width: 8px; height: 8px; border-radius: 50%;
  background: rgb(var(--chip-rgb, 56, 189, 248));
}
.colnav-name {
  flex: 1 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: left;
}
.colnav-caret { flex: 0 0 auto; color: var(--text-4); font-size: 0.7rem; }
.colnav-pill[aria-expanded="true"] .colnav-caret { color: var(--text-2); }

/* ---- Collection menu ---------------------------------------------------- */
/* Two presentations of one list. Desktop: a dropdown anchored under the topbar
   pill — JS measures the pill and writes --menu-top / --menu-left. Phone: the
   media query at the bottom of this block drops those back to `auto` and the
   panel becomes a bottom sheet. Anchoring goes through custom properties (not
   inline top/left) precisely so the phone rules can win. */
.menu {
  position: fixed; inset: 0; z-index: 70;
  --menu-top: calc(var(--topbar-h) + 8px);
  --menu-left: 50%;
  --menu-max: 62vh;
}
.menu[hidden] { display: none; }
.menu-backdrop {
  position: absolute; inset: 0;
  background: rgba(3, 3, 4, 0.5);
  animation: menu-fade 0.18s ease;
}
.menu-panel {
  position: absolute; z-index: 1;
  top: var(--menu-top); left: var(--menu-left);
  width: min(380px, calc(100vw - 1.6rem));
  max-height: var(--menu-max);
  display: flex; flex-direction: column;
  padding: 0.5rem 0.7rem 0.7rem;
  background: var(--panel-solid);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.7);
  animation: menu-drop 0.16s cubic-bezier(0.2, 0.8, 0.3, 1);
}
@keyframes menu-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes menu-drop { from { transform: translateY(-8px); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes menu-up { from { transform: translateY(14%); opacity: 0; } to { transform: none; opacity: 1; } }
.menu-grip { display: none; }
.menu-head { display: flex; align-items: center; justify-content: space-between; padding: 0.2rem 0.2rem 0.6rem; }
.menu-head h2 {
  font-family: var(--font-display); font-size: 0.78rem; font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--text-4);
}
.menu-close {
  width: 32px; height: 32px; border-radius: 9px;
  border: 1px solid var(--border); background: transparent; color: var(--text-2);
  font-size: 0.85rem; cursor: pointer;
}
.menu-close:hover { color: var(--text); border-color: var(--text-4); }
.menu-list { list-style: none; overflow-y: auto; -webkit-overflow-scrolling: touch; }
/* A row is jump-button + download-button side by side — hence the <li> wrapper
   rather than one big button (a button can't legally contain another). */
.menu-row {
  display: flex; align-items: center; gap: 0.25rem;
  border-bottom: 1px solid var(--border-soft);
  border-radius: 12px;
}
.menu-row.is-active {
  background: rgba(var(--chip-rgb, 56, 189, 248), 0.12);
  box-shadow: inset 0 0 0 1px rgba(var(--chip-rgb, 56, 189, 248), 0.4);
}
.menu-item {
  flex: 1 1 auto; min-width: 0;
  display: flex; align-items: center; gap: 0.75rem;
  padding: 0.7rem 0.5rem; border: 0; border-radius: 12px;
  background: transparent; color: var(--text); text-align: left; cursor: pointer;
  font-family: var(--font-body);
}
.menu-item:hover { background: rgba(255, 255, 255, 0.04); }
.menu-emoji { flex: 0 0 auto; font-size: 1.25rem; line-height: 1; width: 1.6rem; text-align: center; }
.menu-emoji.is-dot {
  width: 10px; height: 10px; border-radius: 50%;
  background: rgb(var(--chip-rgb, 56, 189, 248)); margin: 0 0.4rem;
}
.menu-text { flex: 1 1 auto; min-width: 0; }
.menu-name {
  display: block; font-family: var(--font-display); font-weight: 600; font-size: 0.95rem;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.menu-meta { display: block; font-size: 0.76rem; color: var(--text-4); margin-top: 0.1rem; }
.menu-go { flex: 0 0 auto; color: var(--text-4); font-size: 1rem; }
/* Per-row collection download — zips the originals without leaving the menu. */
.menu-dl {
  flex: 0 0 auto;
  width: 34px; height: 34px; margin-right: 0.25rem;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--border-soft); border-radius: 9px;
  background: transparent; color: var(--text-3); cursor: pointer;
}
.menu-dl:hover:not(:disabled) {
  color: var(--text); border-color: rgba(var(--chip-rgb, 56, 189, 248), 0.6);
  background: rgba(var(--chip-rgb, 56, 189, 248), 0.12);
}
.menu-dl:disabled { opacity: 0.45; cursor: progress; }
/* The ⤓ has no room for a "Zipping 12/26…" label, so the one that's working
   pulses and reports progress in its tooltip (see zipCollection). */
.menu-dl.is-busy { opacity: 1; animation: dl-pulse 1.1s ease-in-out infinite; }
.menu-dl.is-busy svg { color: rgb(var(--chip-rgb, 56, 189, 248)); }
@keyframes dl-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }
.menu-dl svg { width: 15px; height: 15px; }

/* ---- Hero --------------------------------------------------------------- */
.hero {
  position: relative; min-height: 100vh;
  display: flex; align-items: center; justify-content: center;
  padding: calc(var(--topbar-h) + 2rem) 1.5rem 3rem;
  overflow: hidden;
}
.hero-grid {
  position: absolute; inset: 0;
  background-image:
    linear-gradient(rgba(56, 189, 248, 0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(56, 189, 248, 0.05) 1px, transparent 1px);
  background-size: 64px 64px;
  mask-image: radial-gradient(ellipse 70% 60% at 50% 40%, #000 0%, transparent 75%);
  -webkit-mask-image: radial-gradient(ellipse 70% 60% at 50% 40%, #000 0%, transparent 75%);
}
.hero-inner { position: relative; max-width: 880px; text-align: center; }
.hero-eyebrow {
  font-family: var(--font-display); font-size: 0.8rem; font-weight: 600;
  letter-spacing: 0.18em; text-transform: uppercase; color: var(--accent);
  margin-bottom: 1.4rem;
}
.hero-title {
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(2.6rem, 8vw, 5.6rem); line-height: 1.02;
  letter-spacing: -0.03em;
  background: linear-gradient(180deg, #ffffff, #b6b6bd);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.hero-amp { color: var(--accent); -webkit-text-fill-color: var(--accent); }
.hero-lede {
  margin: 1.6rem auto 0; max-width: 580px;
  font-size: clamp(1rem, 2.2vw, 1.18rem); color: var(--text-3);
}
.hero-stats {
  display: flex; flex-wrap: wrap; justify-content: center; gap: 0.8rem;
  margin-top: 2.4rem;
}
.stat {
  display: flex; flex-direction: column; align-items: center;
  padding: 0.85rem 1.3rem; border-radius: 14px;
  border: 1px solid var(--border); background: var(--panel);
  backdrop-filter: blur(6px);
}
.stat-num {
  font-family: var(--font-display); font-weight: 700; font-size: 1.6rem;
  color: var(--text);
}
.stat-label {
  font-size: 0.7rem; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--text-4); margin-top: 0.2rem;
}
/* Tool-level share bar — centered under the hero stats. */
.hero-share { display: flex; justify-content: center; margin-top: 1.8rem; }

/* Per-collection share bar — sits inside each cover panel. */
.cover-share { margin-top: 1.4rem; }

.hero-cue {
  margin-top: 3rem; display: flex; flex-direction: column; align-items: center;
  gap: 0.4rem; color: var(--text-4);
}
.hero-cue-text { font-size: 0.72rem; letter-spacing: 0.2em; text-transform: uppercase; }
.hero-cue-arrow { font-size: 1.3rem; animation: bob 1.8s ease-in-out infinite; }
@keyframes bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(8px); } }

/* ---- Timeline section (pinned) ----------------------------------------- */
.timeline {
  position: relative;
  height: 100vh;
  overflow: hidden;
  /* vertical fallback jumps with scrollIntoView — keep the section clear of the
     fixed topbar */
  scroll-margin-top: calc(var(--topbar-h) + 6px);
  background:
    radial-gradient(ellipse 80% 50% at 50% 0%, rgba(var(--accent-rgb), 0.06), transparent 60%),
    var(--bg);
  border-top: 1px solid var(--border-soft);
}
.track {
  display: flex; height: 100%;
  align-items: stretch;
  padding: calc(var(--topbar-h) + 1.2rem) clamp(1rem, 4vw, 3rem) 1.4rem;
  gap: clamp(1rem, 2.5vw, 2rem);
  will-change: transform;
}

/* Section-level progress + label, fixed within the pinned section */
.tl-meter {
  position: absolute; left: clamp(1rem, 4vw, 3rem); bottom: 1.1rem;
  right: clamp(1rem, 4vw, 3rem);
  display: flex; align-items: center; gap: 0.9rem; z-index: 5;
  pointer-events: none;
}
.tl-meter-label {
  font-family: var(--font-display); font-size: 0.78rem; font-weight: 600;
  letter-spacing: 0.04em; color: var(--text-3); white-space: nowrap;
}
.tl-meter-bar {
  flex: 1; height: 2px; background: rgba(255, 255, 255, 0.08); border-radius: 2px;
  position: relative; overflow: hidden;
}
.tl-meter-fill {
  position: absolute; left: 0; top: 0; bottom: 0; width: 0%;
  background: rgb(var(--accent-rgb)); border-radius: 2px;
}

/* ---- Panels ------------------------------------------------------------- */
.panel {
  flex: 0 0 auto;
  width: min(92vw, 1140px);
  height: 100%;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  gap: 0.85rem;
}
.panel-meta {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
}
.panel-meta-right { display: flex; align-items: center; gap: 0.6rem; }
.panel-kicker {
  font-family: var(--font-display); font-weight: 600;
  font-size: 0.82rem; letter-spacing: 0.1em; text-transform: uppercase;
  color: rgb(var(--accent-rgb));
}
.panel-index {
  font-family: ui-monospace, monospace; font-size: 0.8rem; color: var(--text-4);
}
.panel-index b { color: var(--text-2); font-weight: 600; }

.panel-figure {
  position: relative; min-height: 0; border-radius: 16px; overflow: hidden;
  border: 1px solid var(--border);
  background: #0a0a0c center/cover no-repeat;
  box-shadow: 0 30px 60px -30px rgba(0, 0, 0, 0.9);
}
.panel-figure::before {
  /* blurred placeholder backdrop */
  content: ""; position: absolute; inset: -8%;
  background-image: var(--ph); background-size: cover; background-position: center;
  filter: blur(28px) saturate(120%) brightness(0.6);
  transform: scale(1.1); z-index: 0;
}
.panel-figure::after {
  content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.05);
  background: linear-gradient(180deg, transparent 60%, rgba(0, 0, 0, 0.25));
}
.panel-figure img {
  position: relative; z-index: 1;
  width: 100%; height: 100%; object-fit: contain;
  opacity: 0; transition: opacity 0.5s ease;
}
.panel-figure img.loaded { opacity: 1; }

.panel-card {
  border: 1px solid var(--border);
  border-left: 3px solid rgb(var(--accent-rgb));
  background: var(--panel); backdrop-filter: blur(8px);
  border-radius: 14px; padding: 0.95rem 1.15rem;
}
.panel-title {
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(1.3rem, 2.6vw, 1.9rem); line-height: 1.1;
  letter-spacing: -0.02em; color: var(--text);
}
.panel-subtitle {
  margin-top: 0.2rem; font-size: 0.95rem; font-weight: 500; color: var(--text-2);
}
.panel-caption {
  margin-top: 0.5rem; font-size: 0.92rem; color: var(--text-3);
  max-width: 70ch;
}
.panel-chips { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.7rem; }
.chip {
  font-size: 0.72rem; font-weight: 500; color: var(--text-2);
  padding: 0.22rem 0.6rem; border-radius: 999px;
  border: 1px solid var(--border-soft);
  background: rgba(var(--accent-rgb), 0.07);
}

/* ---- Downloads ---------------------------------------------------------- */
/* Two grains: one panel's original PNG (a plain <a download>, no JS, no memory
   cost), and a whole collection zipped in the browser via ToolZip. The zip
   buttons state their size up front — a collection can run past 150 MB. */
.dl-btn {
  display: inline-flex; align-items: center; gap: 0.45rem;
  padding: 0.42rem 0.75rem; border-radius: 9px;
  border: 1px solid var(--border); background: rgba(24, 24, 27, 0.6);
  color: var(--text-2); cursor: pointer;
  font-family: var(--font-body); font-size: 0.78rem; font-weight: 600;
  line-height: 1.2; white-space: nowrap;
  transition: color 0.15s, background 0.15s, border-color 0.15s;
}
.dl-btn:hover:not(:disabled) {
  color: var(--text);
  border-color: rgba(var(--accent-rgb), 0.6);
  background: rgba(var(--accent-rgb), 0.14);
}
.dl-btn:disabled { cursor: progress; opacity: 0.75; }
.dl-btn svg { width: 14px; height: 14px; flex: 0 0 auto; }
.dl-btn.is-primary {
  color: var(--text);
  border-color: rgba(var(--accent-rgb), 0.5);
  background: rgba(var(--accent-rgb), 0.14);
}
.dl-size { color: var(--text-4); font-weight: 500; }
.dl-btn:hover:not(:disabled) .dl-size { color: var(--text-3); }

/* Per-panel: the original PNG, sitting next to the NN / NN index. */
.panel-dl { padding: 0.3rem 0.6rem; font-size: 0.74rem; }

/* ---- Panel metadata card (ⓘ Details) ----------------------------------- */
/* The image's whole sidecar, hanging off the button in the panel's meta row:
   hover peeks, click pins. It drops OVER the illustration rather than pushing
   the layout around — the panel is a fixed-height grid inside a pinned section,
   so anything that changed its height would re-measure every ScrollTrigger. */
.meta-wrap { position: relative; display: inline-flex; }
.panel-info { padding: 0.3rem 0.6rem; font-size: 0.74rem; }
.panel-info.is-open {
  color: var(--text);
  border-color: rgba(var(--accent-rgb), 0.6);
  background: rgba(var(--accent-rgb), 0.14);
}
.meta-pop {
  position: absolute; top: calc(100% + 0.5rem); right: 0; z-index: 20;
  width: min(620px, 78vw);
  /* Bounded by the viewport, not by content: a sidecar with a long moment list
     runs past the panel otherwise. The body scrolls inside. */
  max-height: min(62vh, 520px);
  display: flex; flex-direction: column;
  border: 1px solid var(--border);
  border-top: 2px solid rgb(var(--accent-rgb));
  border-radius: 14px;
  background: rgba(9, 9, 11, 0.96);
  backdrop-filter: blur(10px);
  box-shadow: 0 30px 70px -20px rgba(0, 0, 0, 0.95);
  text-align: left; cursor: default;
  animation: metaIn 0.16s ease-out;
}
@keyframes metaIn {
  from { opacity: 0; transform: translateY(-6px); }
  to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) { .meta-pop { animation: none; } }
.meta-pop.is-pinned { border-color: rgba(var(--accent-rgb), 0.45); }

.meta-pop-head {
  display: flex; align-items: center; justify-content: space-between; gap: 0.75rem;
  padding: 0.7rem 0.9rem; border-bottom: 1px solid var(--border-soft);
}
.meta-pop-title {
  font-family: var(--font-display); font-weight: 600; font-size: 0.9rem;
  color: var(--text); line-height: 1.25;
}
.meta-pop-close {
  flex: 0 0 auto; width: 24px; height: 24px; border-radius: 7px;
  border: 1px solid var(--border-soft); background: transparent;
  color: var(--text-4); cursor: pointer; font-size: 0.75rem; line-height: 1;
}
.meta-pop-close:hover { color: var(--text); border-color: var(--border); }

.meta-pop-body {
  overflow-y: auto; -webkit-overflow-scrolling: touch;
  padding: 0.8rem 0.9rem 0.9rem;
  font-size: 0.8rem; color: var(--text-3);
  overscroll-behavior: contain;   /* don't scrub the timeline while reading */
}
.meta-h {
  font-family: var(--font-display); font-size: 0.7rem; font-weight: 600;
  letter-spacing: 0.1em; text-transform: uppercase;
  color: rgb(var(--accent-rgb));
  margin: 0.95rem 0 0.4rem;
}
.meta-pop-body > *:first-child { margin-top: 0; }
.meta-p { margin: 0.35rem 0; line-height: 1.55; }

.meta-fields {
  display: grid; grid-template-columns: minmax(6rem, auto) 1fr;
  gap: 0.22rem 0.75rem; align-items: baseline;
}
.meta-fields dt { color: var(--text-4); font-size: 0.74rem; }
.meta-fields dd { color: var(--text-2); }

.meta-list { list-style: none; display: grid; gap: 0.45rem; }
.meta-list li {
  position: relative; padding-left: 0.85rem; color: var(--text-2); line-height: 1.5;
}
.meta-list li::before {
  content: ""; position: absolute; left: 0; top: 0.55em;
  width: 4px; height: 4px; border-radius: 50%;
  background: rgba(var(--accent-rgb), 0.7);
}
.meta-sub { display: block; color: var(--text-4); font-size: 0.76rem; margin-top: 0.12rem; }

.meta-links { list-style: none; display: grid; gap: 0.3rem; }
.meta-links a {
  color: var(--text-2); text-decoration: underline;
  text-decoration-color: rgba(var(--accent-rgb), 0.4); text-underline-offset: 3px;
  overflow-wrap: anywhere;
}
.meta-links a:hover { color: rgb(var(--accent-rgb)); }

/* The generation prompt — 2-3 KB of instructions, collapsed so it can't bury
   the facts above it. */
.meta-code { margin-top: 0.9rem; }
.meta-code summary {
  cursor: pointer; list-style: none;
  font-family: var(--font-display); font-size: 0.7rem; font-weight: 600;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-3);
  padding: 0.4rem 0.6rem; border: 1px solid var(--border-soft); border-radius: 8px;
}
.meta-code summary::-webkit-details-marker { display: none; }
.meta-code summary:hover { color: var(--text); border-color: rgba(var(--accent-rgb), 0.5); }
.meta-code[open] summary { border-color: rgba(var(--accent-rgb), 0.5); color: var(--text); }
.meta-code pre {
  margin-top: 0.5rem; padding: 0.7rem 0.8rem; border-radius: 8px;
  background: rgba(0, 0, 0, 0.5); border: 1px solid var(--border-soft);
  font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 0.72rem;
  line-height: 1.55; color: var(--text-3);
  white-space: pre-wrap; overflow-wrap: anywhere;
}

.meta-pop-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 0.75rem;
  padding: 0.55rem 0.9rem; border-top: 1px solid var(--border-soft);
  font-size: 0.72rem; color: var(--text-4);
}
.meta-pop-foot a { color: rgb(var(--accent-rgb)); }
.meta-pop-foot a:hover { text-decoration: underline; }
.meta-pop-file {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Per-collection: on the cover panel, under the share bar. */
.cover-dl { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 1rem; }

/* ---- Cover panel (first in each track) --------------------------------- */
.panel.cover {
  width: min(80vw, 560px);
  grid-template-rows: 1fr; align-content: center;
}
.cover-inner {
  border: 1px solid var(--border); border-radius: 20px;
  background:
    radial-gradient(ellipse 100% 80% at 0% 0%, rgba(var(--accent-rgb), 0.14), transparent 60%),
    var(--panel-solid);
  padding: clamp(1.6rem, 4vw, 2.6rem); height: fit-content;
}
.cover-emoji { font-size: 2.6rem; line-height: 1; }
.cover-name {
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(1.8rem, 4vw, 2.8rem); line-height: 1.05;
  letter-spacing: -0.02em; margin-top: 1rem;
}
.cover-span {
  display: inline-block; margin-top: 0.9rem;
  font-family: var(--font-display); font-weight: 600; font-size: 0.8rem;
  letter-spacing: 0.06em; color: rgb(var(--accent-rgb));
  border: 1px solid rgba(var(--accent-rgb), 0.4); border-radius: 999px;
  padding: 0.3rem 0.8rem;
}
.cover-blurb { margin-top: 1.2rem; color: var(--text-3); font-size: 1rem; max-width: 42ch; }
.cover-cue {
  margin-top: 1.6rem; display: inline-flex; align-items: center; gap: 0.5rem;
  font-size: 0.78rem; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--text-4);
}
.cover-cue .arrow { animation: nudge 1.6s ease-in-out infinite; color: rgb(var(--accent-rgb)); }
@keyframes nudge { 0%, 100% { transform: translateX(0); } 50% { transform: translateX(7px); } }

/* ---- End panel ---------------------------------------------------------- */
.panel.endcap { width: min(70vw, 420px); grid-template-rows: 1fr; align-content: center; }
.endcap-inner { text-align: center; color: var(--text-3); }
.endcap-inner .big { font-family: var(--font-display); font-weight: 700; font-size: 2rem; color: var(--text); }
.endcap-inner .next { margin-top: 1rem; font-size: 0.85rem; letter-spacing: 0.06em; }

/* ---- Footer ------------------------------------------------------------- */
.site-footer {
  border-top: 1px solid var(--border-soft);
  padding: 3rem 1.5rem; text-align: center; color: var(--text-4);
  font-size: 0.88rem;
}
.site-footer a { color: var(--accent); }

/* ---- Reveal animation (entrance) --------------------------------------- */
.reveal { opacity: 0; transform: translateY(34px); }
.reveal.in { opacity: 1; transform: none; transition: opacity 0.6s ease, transform 0.6s cubic-bezier(0.2, 0.7, 0.2, 1); }

/* =========================================================================
   Mobile / touch / reduced-motion fallback — vertical stacking, no pinning
   ========================================================================= */
@media (max-width: 820px), (prefers-reduced-motion: reduce) {
  .timeline { height: auto; overflow: visible; }
  .track {
    flex-direction: column; height: auto;
    padding: calc(var(--topbar-h) + 1.4rem) 1rem 3.5rem;
    gap: 1.6rem; transform: none !important;
    /* Nothing animates the track on this side of the breakpoint, and leaving
       the hint in place would make it a containing block — which pins the
       Details bottom sheet to the track instead of the viewport. */
    will-change: auto;
  }
  .panel {
    width: 100%; height: auto;
    grid-template-rows: auto auto auto;
  }
  .panel-figure { aspect-ratio: 3 / 2; min-height: 0; }
  .panel.cover, .panel.endcap { width: 100%; }
  .tl-meter { display: none; }
  .hero-cue { margin-top: 2rem; }
}

/* Phone topbar: two rows — brand + section selector, then the collection nav.
   (Width-only, unlike the stacking query above: a wide desktop with
   reduced-motion keeps the single-row topbar, which fits there.) */
@media (max-width: 820px) {
  :root { --topbar-h: 100px; }
  .topbar {
    flex-wrap: wrap;
    align-content: center;
    gap: 0.55rem;
    padding-top: 0.45rem;
    padding-bottom: 0.45rem;
  }
  .hint-btn { display: none; }
  .colnav { order: 2; width: 100%; flex: 1 1 100%; margin-left: 0; }

  /* The dropdown becomes a bottom sheet: reachable by thumb, and there is no
     pill on this side of the breakpoint worth anchoring 380px of menu to. */
  .menu { display: flex; align-items: flex-end; }
  .menu-backdrop { background: rgba(3, 3, 4, 0.72); backdrop-filter: blur(3px); }
  .menu-panel {
    position: relative;
    top: auto; left: auto;
    width: 100%; max-height: 76vh;
    padding: 0.5rem 0.9rem calc(1.1rem + env(safe-area-inset-bottom, 0px));
    border: 0; border-top: 1px solid var(--border);
    border-radius: 18px 18px 0 0;
    box-shadow: 0 -20px 60px rgba(0, 0, 0, 0.65);
    animation: menu-up 0.22s cubic-bezier(0.2, 0.8, 0.3, 1);
  }
  .menu-grip {
    display: block;
    width: 42px; height: 4px; border-radius: 999px;
    background: var(--border); margin: 0.25rem auto 0.6rem;
  }

  /* Details becomes a bottom sheet too. There is no hover on a phone, so the
     card is always the pinned (tap) mode — and 620px anchored to a button near
     the screen edge would hang off it. `fixed` is safe here: the track carries
     no transform on this side of the breakpoint. */
  .meta-pop {
    position: fixed;
    top: auto; left: 0.55rem; right: 0.55rem;
    bottom: calc(0.55rem + env(safe-area-inset-bottom, 0px));
    width: auto; max-height: 74vh;
    border-radius: 16px;
  }
  /* Kicker + index + Details + PNG is more than a phone row holds — let it wrap
     rather than shrinking the buttons past a comfortable tap target. */
  .panel-meta { flex-wrap: wrap; row-gap: 0.45rem; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .hero-cue-arrow, .cover-cue .arrow { animation: none; }
  /* The accent-tinted glyph still marks the busy row without the pulse. */
  .menu-dl.is-busy { animation: none; }
  .reveal { opacity: 1; transform: none; }
}

/* ---- Image Studio selector (topbar, far right) ------------------------- */
/* Three-way segmented selector, mirrors the Image Studio bar so every surface
   (this page, the meme wall, the storefront, and the shell) shows the same
   top-right selector. Hidden when embedded (the shell bar covers it). */
/* Shared geometry across the three Image Studio apps — a segment is 0.74rem/1.5
   text + 14px icon in 0.34rem×0.6rem padding, so the control computes to the
   same 37px tall pill everywhere regardless of each page's own line-height. */
/* No `margin-left: auto` here, unlike the sibling apps: the collection nav to
   its left already claims the free space. */
.studio-switch {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: rgba(6, 6, 6, 0.6);
}
.studio-switch[hidden] { display: none; }
.studio-seg {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.34rem 0.6rem;
  border-radius: 999px;
  font-family: var(--font-body);
  font-size: 0.74rem;
  line-height: 1.5;
  font-weight: 600;
  color: var(--text-3);
  text-decoration: none;
  white-space: nowrap;
  transition: background 0.15s, color 0.15s;
}
.studio-seg svg { width: 14px; height: 14px; }
.studio-seg:not(.is-active):hover { color: var(--text); background: rgba(255, 255, 255, 0.06); }
.studio-seg.is-active {
  color: var(--text);
  background: color-mix(in srgb, #a78bfa 20%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, #a78bfa 50%, transparent);
  cursor: default;
}
.studio-seg.is-active svg { color: #a78bfa; }
@media (max-width: 820px) {
  .studio-seg span { display: none; }
  .studio-seg { padding: 0.4rem 0.5rem; }
  /* Row 1 is brand + this selector only (the collection nav wrapped to row 2),
     so the auto margin comes back to hold it at the right edge. */
  .studio-switch { margin-left: auto; }
}
