/* /recommend — "Ask the Atlas" chat page. Mobile-first (375px), tokens only.
   Shared .page-header / .page-eyebrow / .page-title come from css/app.css.
   Task 9: chat/rail/composer styles — full replace of previous vibe-search CSS. */

/* ─── DARK THEME ───────────────────────────────────────────────────────────── */
/* tokens-dark.css (linked in recommend.html, before this file) supplies
   --cream-dim/--border/--border-strong, matching the other 5 dark pages.
   These three have no site-wide equivalent yet and stay page-local. */
:root {
  --cream-field: rgba(227, 218, 201, 0.07);
  --cream-hover: rgba(227, 218, 201, 0.06);
  --cream-soft:  rgba(227, 218, 201, 0.82);
  --cream-edge:  rgba(227, 218, 201, 0.18); /* input/dropdown edge — brighter than --border */
  /* Skeleton shimmer — low-alpha cream on black. --shimmer-hi sweeps across
     --shimmer-base to read as a highlight travelling over the placeholder. */
  --shimmer-base: rgba(227, 218, 201, 0.05);
  --shimmer-hi:   rgba(227, 218, 201, 0.11);
  /* Sticky composer bar's clearance over the fixed mobile bottom-nav.
     layout.js overrides this with the nav's measured height (which already
     includes its safe-area padding); this is the no-JS fallback. */
  --atlas-nav-h: calc(68px + env(safe-area-inset-bottom));
}
html, body { background: var(--black); color: var(--off-white); }

/* ─── MOTION ───────────────────────────────────────────────────────────────── */
/* Soft fade-in (LLM-style: messages fade, they don't slide in). */
@keyframes atlas-rise {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* ─── ACCESSIBILITY HELPER ─────────────────────────────────────────────────── */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ─── SHELL — MOBILE FIRST: single column ──────────────────────────────────── */
.atlas-shell {
  display: block;
  max-width: 1200px;
  margin: 0 auto;
  /* No bottom padding: the composer (.atlas-bottom-bar) is the last item in
     this locked, full-height column and must sit flush above the mobile nav.
     A bottom pad here would reintroduce the dead gap below the composer.
     Desktop restores its own breathing room in the min-width:769px block. */
  padding: 0;
}

/* ─── CHAT VIEWPORT: lock the page — the thread is the only scroller ───────── */
/* The document must NOT scroll on this page. If it can, iOS scrolls the
   window to lift the focused composer above the keyboard, and WebKit (Safari
   and iOS Chrome alike) often leaves that offset stuck after the keyboard
   closes — the fixed .mobile-bottom-nav and sticky .atlas-bottom-bar then
   render ~a keyboard-height above the true bottom with a dead gap below.
   100dvh tracks the visible viewport (100vh is the large viewport on iOS and
   overflows it while browser chrome is showing); overflow:hidden removes
   window scroll entirely so the keyboard has nothing to strand.
   Scoped by :has(.atlas-shell) so no other page is affected. */
html:has(.atlas-shell),
body:has(.atlas-shell) {
  height: 100vh;    /* fallback for pre-dvh browsers */
  height: 100dvh;
  min-height: 0;    /* cancel global min-height:100vh — it would win over the dvh height */
  overflow: hidden;
}
.page-flex-content:has(.atlas-shell) {
  /* Override global flex: 1 0 auto — the wrapper must be allowed to SHRINK to
     the viewport, or the flex chain grows with the conversation and
     .atlas-thread's overflow-y:auto never engages (the document scrolls
     instead, which re-opens the keyboard bug above). */
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
.atlas-shell {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
.atlas-conversation {
  flex: 1 1 auto;
}

/* ─── CONVERSATION SECTION ─────────────────────────────────────────────────── */
.atlas-conversation {
  display: flex;
  flex-direction: column;
  min-height: 0;
}

/* ─── HEADER ───────────────────────────────────────────────────────────────── */
.atlas-head {
  padding: var(--space-8) var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--border);
}

.atlas-eyebrow {
  font-family: var(--font-ui);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--color-accent);
  margin: 0 0 var(--space-2);
}

.atlas-subhead {
  font-family: var(--font-body);
  font-size: var(--text-body);
  line-height: var(--leading-body);
  color: var(--cream-dim);
  margin: 0;
}

/* ─── THREAD (message list) ────────────────────────────────────────────────── */
.atlas-thread {
  flex: 1 1 auto;
  padding: var(--space-6) 0 var(--space-2);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

/* ─── MESSAGES ─────────────────────────────────────────────────────────────── */
.atlas-msg {
  display: flex;
  gap: var(--space-3);
  margin: 0 var(--space-4) var(--space-6);
  align-items: flex-start;
  animation: atlas-rise 400ms cubic-bezier(0.22, 1, 0.36, 1) both;
}

/* User bubbles sit on the right with their avatar on the far right — row-reverse
   puts the avatar (first DOM child) after the bubble, packed to the right. */
.atlas-msg-user {
  flex-direction: row-reverse;
}

/* Consecutive same-speaker messages read as one group: pull the follow-ups up
   toward the previous bubble (their avatar is an inert spacer, not repeated). */
.atlas-msg-grouped {
  margin-top: calc(-1 * var(--space-3));
}

/* No chat bubble box — the user's line reads as a quiet, right-aligned aside. */
.atlas-msg-user .atlas-bubble {
  max-width: 80%;
  text-align: right;
  color: var(--cream-dim);
  font-style: italic;
  padding-top: var(--space-1);
}

.atlas-msg-bot .atlas-bubble {
  max-width: 100%;
}

/* ─── AVATARS ──────────────────────────────────────────────────────────────── */
/* A small disc on every message: the Atlas brand mark for bot turns, a neutral
   cream monogram glyph for the user. First-of-a-group only; grouped follow-ups
   get an empty .atlas-avatar-spacer of the same size to keep bubbles aligned. */
.atlas-avatar {
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.atlas-avatar-spacer {
  background: none;
  border: none;
}

/* Bot: brand mark on a near-black disc with a red-accent ring. */
.atlas-avatar-bot {
  background: var(--color-primary, #0f0f0f);
  border: 1px solid var(--color-accent);
  box-shadow: 0 0 0 3px rgba(192, 57, 43, 0.14);
}

.atlas-avatar-mark {
  width: 22px;
  height: 22px;
  display: block;
}

/* User: neutral cream monogram glyph on a low-alpha cream disc. */
.atlas-avatar-user {
  background: var(--cream-field);
  border: 1px solid var(--cream-edge);
  color: var(--cream-soft);
}

.atlas-avatar-glyph {
  width: 18px;
  height: 18px;
  display: block;
}

/* First-run example prompts under the welcome — tap to drop into the composer. */
.atlas-examples {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-4);
}
.atlas-example {
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  min-height: 36px;
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-pill);
  cursor: pointer;
  background: var(--cream-hover);
  color: var(--cream-soft);
  border: 1px solid var(--border);
  transition: border-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out);
}
.atlas-example:hover {
  border-color: var(--color-accent);
  color: var(--color-base);
}
.atlas-example:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

/* ─── BUBBLE TEXT ──────────────────────────────────────────────────────────── */
.atlas-bubble {
  font-family: var(--font-body);
  font-size: var(--text-body);
  line-height: var(--leading-body);
  color: var(--off-white);
}

.atlas-bubble p {
  margin: 0 0 var(--space-2);
}

.atlas-bubble p:last-child {
  margin-bottom: 0;
}

/* ─── FIRST-RUN EXAMPLE PROMPTS ────────────────────────────────────────────── */
/* Sit under the greeting bubble; clicking one fills the composer (composer.js
   'atlas-example' action) so a first-time visitor isn't facing a blank page. */
.atlas-examples {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-4);
}

.atlas-example {
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  min-height: 36px;
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-pill);
  cursor: pointer;
  background: var(--cream-hover);
  color: var(--cream-soft);
  border: 1px solid var(--border);
  transition: border-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out);
}

.atlas-example:hover {
  border-color: var(--color-accent);
  color: var(--color-base);
}

.atlas-example:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

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

/* ─── "THINKING" ANIMATION ─────────────────────────────────────────────────── */
/* Blank movie-poster placeholders wired together by a flowing red "thread"
   line — as if the Atlas is tracing connections between films (echoes the
   homepage hero's thread technique). Replaces the old shimmer skeleton. The
   copy lives in a .visually-hidden span for the aria-live region; this SVG is
   decorative (aria-hidden). */
.atlas-thinking {
  padding: var(--space-2) var(--space-4);
}

.atlas-thinking-svg {
  width: 100%;
  max-width: 320px;
  height: auto;
  display: block;
  overflow: visible;
}

/* Blank poster placeholders — dark cards with a soft cream tint + a gentle
   staggered pulse so they feel alive while the thread traces between them. */
.atlas-thinking-poster {
  fill: var(--shimmer-base);
  stroke: var(--border);
  stroke-width: 1;
  animation: atlas-poster-pulse 1.8s ease-in-out infinite;
}
.atlas-thinking-poster--0 { animation-delay: 0s; }
.atlas-thinking-poster--1 { animation-delay: 0.3s; }
.atlas-thinking-poster--2 { animation-delay: 0.6s; }

/* Dim base rail the flow travels along (same treatment as the hero threads). */
.atlas-thinking-base {
  fill: none;
  stroke: var(--color-accent);
  stroke-width: 2;
  opacity: 0.22;
}

/* Flowing red dashes. Seamless loop: dasharray 2 11 -> period 13; the offset
   moves a whole multiple of the period (-39 = 3 x 13) so the pattern lines up
   exactly at cycle end — no jump. */
.atlas-thinking-flow {
  fill: none;
  stroke: var(--color-accent);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-dasharray: 2 11;
  animation: atlas-threadflow 1.5s linear infinite;
}

@keyframes atlas-threadflow { to { stroke-dashoffset: -39; } }
@keyframes atlas-poster-pulse {
  0%, 100% { opacity: 0.5; }
  50%      { opacity: 1; }
}

/* ─── ERROR TURN ───────────────────────────────────────────────────────────── */
.atlas-error {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-4);
  padding: 0 var(--space-4);
}

.atlas-error-text {
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--text-body);
  line-height: var(--leading-body);
  color: var(--cream-soft);
}

/* ─── COMPOSER (sticky input bar) ──────────────────────────────────────────── */
/* REQUIRED: Clears global .mobile-bottom-nav (68px) on mobile */
/* Sticks the chip row + composer together as one unit, so escape-hatch
   actions (e.g. "Search a different film") are always reachable without
   scrolling — sticking each piece separately would need fragile pixel-math
   to stack their offsets correctly. */
.atlas-bottom-bar {
  /* The page is locked (body: 100dvh + overflow:hidden — see the CHAT VIEWPORT
     block) and .atlas-thread is the only scroller, so the composer is simply
     the last item in the full-height column and rests at the bottom on its own.
     It must NOT be sticky: body's overflow:hidden makes it the sticky scrollport,
     and `bottom: 68px` then stacked on top of body's own 68px nav padding —
     lifting the composer ~a nav-height off the bottom (the dead-gap bug). */
  background: var(--black);
  padding-bottom: var(--space-3);
}

.atlas-composer {
  display: flex;
  gap: var(--space-2);
  align-items: flex-end; /* keep the send button pinned to the bottom as the textarea grows */
  padding: var(--space-3) var(--space-4);
  background: var(--black);
  border-top: 1px solid var(--border);
}

.atlas-input {
  flex: 1 1 auto;
  min-height: 44px;
  max-height: 160px;              /* safety cap; JS caps growth at ~5 rows */
  font-family: var(--font-body);
  font-size: var(--text-body); /* >=16px: prevents iOS auto-zoom */
  line-height: var(--leading-ui);
  color: var(--off-white);
  background: var(--cream-hover);
  border: 1px solid var(--cream-edge);   /* matches the typeahead dropdown's edge */
  border-radius: var(--radius);
  padding: var(--space-3) var(--space-4);
  resize: none;
  overflow-y: hidden;             /* JS flips to auto once content exceeds the cap */
}

.atlas-input::placeholder {
  color: var(--cream-dim);
}

.atlas-input:focus-visible {
  outline: none;
  border-color: var(--color-accent);
  box-shadow: 0 0 0 3px rgba(192, 57, 43, 0.18);
}

.atlas-send {
  flex: 0 0 auto;
  min-width: 44px;
  min-height: 44px;
  background: var(--color-accent);
  color: var(--color-base-bright);
  border: none;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-body);
  cursor: pointer;
  transition: opacity var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}

.atlas-send:hover {
  opacity: 0.88;
}

.atlas-send:active {
  transform: scale(0.94);
}

/* ─── RESET BUTTON ("Ask about another film") ──────────────────────────────── */
/* Round icon-only button beside the composer that reuses atlas-search-different
   (clear → greeting → focus input). Shown only while a settled result is on
   screen — results.js toggles [hidden] in setChips(), in step with the chips. */
.atlas-reset {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  color: var(--color-accent);            /* the refresh glyph (SVG uses currentColor) */
  background: none;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease-out);
}
.atlas-reset[hidden] { display: none; }  /* override .atlas-reset's own display */
.atlas-reset:hover { border-color: var(--color-accent); }
.atlas-reset:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 3px; }

.atlas-send:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

.atlas-send:disabled {
  opacity: 0.5;
  cursor: default;
  transform: none;
}

/* ─── DESKTOP: single centered column (rail removed) ───────────────────────── */
@media (min-width: 769px) {
  .atlas-shell {
    max-width: 820px;
    /* Desktop has no mobile nav; keep a little breathing room below the
       composer (the mobile shell zeroes this so the composer meets the nav). */
    padding: 0 var(--space-6) var(--space-10);
  }

  .atlas-head {
    padding: var(--space-10) 0 var(--space-5);
  }
}

/* ─── REDUCED MOTION ───────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .atlas-send,
  .atlas-reset,
  .atlas-input {
    transition: none;
  }
  .atlas-msg {
    animation: none;
  }
  /* Hold a static state — no marching dashes, no poster pulse. The dim base
     rail + blank posters stay visible so the placeholder still reads. */
  .atlas-thinking-flow,
  .atlas-thinking-poster {
    animation: none;
  }
  .atlas-thinking-poster {
    opacity: 0.7;
  }
}

/* ─── Composer typeahead drop-UP ──────────────────────────────────────────── */
/* The composer is pinned to the viewport bottom (and the keyboard sits right
   below it on mobile), so suggestions open UPWARD into the conversation area —
   the only direction with guaranteed room. column-reverse keeps the #1 match
   visually adjacent to the input (Slack/Discord pattern) while the DOM (and
   screen-reader order) stays best-match-first. */
.atlas-suggest {
  position: absolute; bottom: 100%; left: 0; right: 0; margin-bottom: var(--space-2);
  background: var(--color-primary); border: 1px solid rgba(227,218,201,0.18);
  border-radius: 10px; z-index: 20;
  display: flex; flex-direction: column-reverse;
  max-height: min(320px, 45dvh);
  overflow-y: auto;
}
/* Explicit display above would defeat the hidden attribute — restore it. */
.atlas-suggest[hidden] { display: none; }
.atlas-opt {
  display: flex; flex-direction: column; gap: var(--space-1); width: 100%; text-align: left;
  padding: var(--space-3) var(--space-4); background: transparent; border: none; cursor: pointer;
  color: var(--color-base);
  /* Reversed stack: each row's border-TOP is the separator from the row shown
     above it; the first (best, bottom-most) row draws none at the panel edge. */
  border-top: 1px solid rgba(227,218,201,0.08);
}
.atlas-opt:first-child { border-top: none; }
.atlas-opt:hover, .atlas-opt-active { background: rgba(227,218,201,0.06); }
.atlas-opt-t { font-family: var(--font-body); font-size: var(--text-body); }
.atlas-opt-m { font-family: var(--font-ui); font-size: var(--text-xs); color: var(--cream-dim); }

/* ─── ONE-AT-A-TIME RESULTS (lineage thread + shelf) ────────────────────────── */
.atlas-badge-row {
  display: flex; align-items: center; gap: var(--space-2);
  margin-bottom: var(--space-4);
}
/* One eyebrow treatment for every turn (vibe / by-feel / lineage) so the
   thread reads consistently — the label text is what distinguishes them. */
.atlas-badge {
  font-family: var(--font-ui); font-size: var(--text-xs);
  letter-spacing: var(--tracking-eyebrow); text-transform: uppercase;
  color: var(--color-accent); font-weight: var(--weight-medium);
}
.atlas-badge-dot {
  width: 4px; height: 4px; border-radius: 999px; background: var(--cream-dim);
}
.atlas-badge-meta { font-family: var(--font-ui); font-size: var(--text-xs); color: var(--cream-dim); }

.atlas-bridge {
  font-family: var(--font-body); font-size: var(--text-bridge);
  line-height: var(--leading-bridge); margin: 0 0 var(--space-4); max-width: 56ch;
}

/* ─── HYBRID TURN: grounded RAG answer above the film picks ──────────────────
   Prepended into the same turn node ABOVE the recommender's shelf. Editorial
   prose (Lora / --font-body) on the black/red dark theme, separated from the
   picks below by a hairline rule. Additive — absent entirely when the RAG
   answer is off or ungrounded, so the shelf reads exactly as it does today. */
.atlas-answer {
  margin: 0 0 var(--space-5); padding: 0 0 var(--space-5);
  border-bottom: 1px solid var(--border);
}
.atlas-answer-body {
  font-family: var(--font-body); font-size: var(--text-bridge);
  line-height: var(--leading-bridge); color: var(--color-base); max-width: 60ch;
}
.atlas-answer-body p { margin: 0 0 var(--space-3); }
.atlas-answer-body p:last-child { margin-bottom: 0; }

/* Citation chips — the cited films. Smaller than the action chips; a tap opens
   the existing slide-in card (atlas-open-card) for that film_id. */
.atlas-cite-row {
  display: flex; align-items: center; gap: var(--space-2);
  flex-wrap: wrap; margin-top: var(--space-4);
}
.atlas-cite-label {
  font-family: var(--font-ui); font-size: var(--text-xs);
  letter-spacing: var(--tracking-eyebrow); text-transform: uppercase;
  color: var(--cream-dim); margin-right: var(--space-1);
}
.atlas-cite {
  font-family: var(--font-ui); font-size: var(--text-xs);
  padding: var(--space-1) var(--space-3); min-height: 32px;
  border-radius: var(--radius-pill); cursor: pointer;
  background: transparent; color: var(--cream-dim);
  border: 1px solid var(--border-strong);
}
.atlas-cite:hover { border-color: var(--color-accent); color: var(--color-accent); }
.atlas-cite:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }

/* Ungrounded fallback line (no relevant material / guide briefly down). Quiet
   and non-alarming — the film shelf below is the real answer. */
.atlas-rag-note {
  font-family: var(--font-ui); font-size: var(--text-sm);
  color: var(--cream-dim); font-style: italic;
  margin: 0 0 var(--space-4); max-width: 56ch;
}

.atlas-trail { display: flex; flex-direction: column; gap: var(--space-4); margin-bottom: var(--space-4); }
.atlas-trail-item { opacity: 0.55; display: flex; align-items: baseline; gap: var(--space-3); flex-wrap: wrap; }
.atlas-trail-title { font-family: var(--font-display); font-size: var(--text-body); font-weight: var(--weight-semibold); }
.atlas-trail-meta { font-family: var(--font-ui); font-size: var(--text-sm); color: var(--cream-dim); }

.atlas-stop-label, .atlas-tease-label {
  font-family: var(--font-ui); font-size: var(--text-xs);
  letter-spacing: var(--tracking-eyebrow); text-transform: uppercase; color: var(--cream-dim);
  display: block; margin-bottom: var(--space-3);
}
/* No bottom margin here — the chip row used to render inline right after
   this block, so this margin separated content from chips. Now the chip
   row lives in the persistent #atlas-chip-bar outside this element, and
   .atlas-msg's own margin-bottom (--space-8) plus .atlas-thread's bottom
   padding already provide the gap before the divider; stacking this on
   top of those left a much larger gap here than below the divider. */
.atlas-current-stop, .atlas-terminus { margin-bottom: 0; }
.atlas-stop-body { display: flex; flex-direction: column; gap: var(--space-4); }
/* Mobile: a compact centered poster so the title + synopsis below it stay in
   view without scrolling once an answer lands (poster-above-copy stack per the
   mobile-first DNA pattern, just smaller). Desktop restores the larger poster
   in the row layout below. */
.atlas-stop-poster { width: 100%; max-width: 130px; margin: 0 auto; }
/* The terminus renders a bare <img> (real anchor poster, not a tile_html
   card) — give it the same aspect-ratio/border treatment the stop tiles
   above it get, so it doesn't look inconsistent at the end of the thread. */
.atlas-stop-poster > img {
  width: 100%; aspect-ratio: 2 / 3; object-fit: cover;
  border-radius: var(--radius-sm); border: 1px solid var(--border);
}
/* .film-card's box/overlay CSS isn't in the shared components/film-card.css
   (that file is overlay-position only) — tile_html reused here needs its
   own copy or the poster renders unconstrained (natural image size) with
   the title/meta overlay flowing as plain text instead of an absolute
   gradient overlay. */
.atlas-stop-poster .film-card-link {
  width: 100%; display: block; text-decoration: none; color: inherit;
}
.atlas-stop-poster .film-card {
  width: 100%; aspect-ratio: 2 / 3; position: relative; overflow: hidden;
  border-radius: var(--radius-sm); background: var(--color-primary);
  border: 1px solid var(--border);
}
.atlas-stop-poster .film-card-placeholder {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  padding: var(--space-4); background: rgba(242, 237, 228, 0.08);
}
.atlas-stop-poster .film-card-placeholder-text {
  font-family: var(--font-display); font-size: var(--text-body); font-style: italic;
  color: var(--cream-dim); text-align: center; line-height: var(--leading-ui);
}
.atlas-stop-poster .film-card-info {
  min-height: 0; padding: var(--space-6) var(--space-3) var(--space-3);
  background: linear-gradient(to bottom,
    rgba(10, 10, 10, 0) 0%, rgba(10, 10, 10, 0.5) 50%, rgba(10, 10, 10, 0.92) 100%);
}
.atlas-stop-poster .film-card-title {
  font-family: var(--font-display); font-size: var(--text-h3); font-style: italic;
  color: var(--off-white); line-height: var(--leading-snug); margin-bottom: var(--space-1);
  overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
.atlas-stop-poster .film-card-meta {
  font-family: var(--font-ui); font-size: var(--text-sm); color: var(--cream-dim);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.atlas-stop-title { font-family: var(--font-display); font-size: var(--text-h2); font-weight: var(--weight-bold); line-height: var(--leading-tight); }
.atlas-stop-meta { font-family: var(--font-ui); font-size: var(--text-sm); color: var(--cream-dim); margin-top: var(--space-1); }
.atlas-stop-blurb { font-family: var(--font-body); font-size: var(--text-body); line-height: var(--leading-body); color: rgba(227, 218, 201, 0.85); margin: var(--space-2) 0 0; max-width: 44ch; }
.atlas-poster-placeholder {
  aspect-ratio: 2 / 3; border-radius: var(--radius-sm); border: 1px solid var(--border);
  background: var(--cream-hover); display: flex; align-items: center; justify-content: center;
  padding: var(--space-4); text-align: center; font-family: var(--font-display); color: var(--cream-dim);
}

.atlas-next-tease { opacity: 0.55; }
.atlas-tease-title { font-family: var(--font-display); font-size: var(--text-h3); font-weight: var(--weight-semibold); }

.atlas-chip-row { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; border-top: 1px solid var(--border); padding-top: var(--space-5); }
/* #atlas-chip-bar is the persistent chip-row slot inside .atlas-bottom-bar
   (see recommend.html) — results.js renders each turn's chips into it, so
   they're always reachable without scrolling, sticky alongside the composer. */
#atlas-chip-bar { padding: var(--space-6) var(--space-4) var(--space-4); margin: 0; }
#atlas-chip-bar[hidden] { display: none; }
.atlas-chip {
  font-family: var(--font-ui); font-size: var(--text-sm); min-height: 44px;
  padding: var(--pad-button); border-radius: var(--radius-pill); cursor: pointer;
  background: transparent; color: var(--color-base); border: 1px solid var(--border-strong);
}
.atlas-chip:hover { border-color: var(--color-accent); color: var(--color-accent); }
.atlas-chip:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
.atlas-chip-primary { background: var(--color-accent); color: var(--color-base-bright); border-color: var(--color-accent); }
/* .atlas-chip:hover's text color (--color-accent) is meant for secondary
   chips (transparent background) — on a primary chip, whose background is
   already --color-accent, that made the text invisible on hover. */
.atlas-chip-primary:hover { color: var(--color-base-bright); opacity: 0.88; }

/* Quiet escape-hatch link — see chipLink() in results.js. No pill/border;
   keeps a 44px tap target via padding for touch accessibility. */

.atlas-entering { animation: atlas-turn-enter var(--dur) ease-out both; }
@keyframes atlas-turn-enter {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .atlas-entering { animation: none; }
}

@media (min-width: 769px) {
  .atlas-stop-body { flex-direction: row; align-items: flex-start; gap: var(--space-8); }
  .atlas-stop-poster { flex: 0 0 220px; margin: 0; }
}

/* Legacy counter kept for restored-state safety; superseded by .atlas-carousel. */
.atlas-shelf-counter {
  font-family: var(--font-ui); font-size: var(--text-xs); color: var(--cream-dim);
}

/* ─── SHELF: layered deck + prev/next carousel (ported from staging) ────────── */
/* Prev/next controls + a "3 / 12" position (trailing "+" when the server still
   has more to fetch), pushed to the right of the chip row so it's obvious the
   shelf continues and is easy to shuffle through. */
.atlas-carousel {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-left: auto;
}
.atlas-carousel-btn {
  flex: 0 0 auto;
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-body);
  line-height: 1;
  border-radius: 50%;
  cursor: pointer;
  background: transparent;
  color: var(--color-base);
  border: 1px solid var(--border-strong);
  transition: border-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out);
}
.atlas-carousel-btn:hover:not(:disabled) {
  border-color: var(--color-accent);
  color: var(--color-accent);
}
.atlas-carousel-btn:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}
.atlas-carousel-btn:disabled {
  opacity: 0.4;
  cursor: default;
}
.atlas-carousel-pos {
  font-family: var(--font-ui);
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
  color: var(--cream-dim);
  min-width: 3.5ch;
  text-align: center;
}

/* Layered peek: a faint offset card edge behind the current poster's right
   side, hinting the next film is stacked behind it. Only when more remain. */
.atlas-current-stop.atlas-has-next .atlas-stop-poster {
  position: relative;
}
.atlas-current-stop.atlas-has-next .atlas-stop-poster::after {
  content: "";
  position: absolute;
  top: 6px;
  bottom: 6px;
  right: -8px;
  width: 10px;
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  background: var(--cream-field);
  border: 1px solid var(--border);
  border-left: none;
  z-index: -1;
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .atlas-carousel-btn,
  .atlas-example { transition: none; }
}

/* ─── SHELF MINI-CAROUSEL ──────────────────────────────────────────────────── */
/* Prev/next controls + a "3 / 12" position indicator (trailing "+" when the
   server still has more to fetch), pushed to the right of the chip row. Makes
   it obvious at a glance that the shelf continues and is easy to browse. */
.atlas-carousel {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-left: auto;
}

.atlas-carousel-btn {
  flex: 0 0 auto;
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-body);
  line-height: 1;
  border-radius: 50%;
  cursor: pointer;
  background: transparent;
  color: var(--color-base);
  border: 1px solid var(--border-strong);
  transition: border-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out);
}

.atlas-carousel-btn:hover:not(:disabled) {
  border-color: var(--color-accent);
  color: var(--color-accent);
}

.atlas-carousel-btn:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

.atlas-carousel-btn:disabled {
  opacity: 0.4;
  cursor: default;
}

.atlas-carousel-pos {
  font-family: var(--font-ui);
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
  color: var(--cream-dim);
  min-width: 3.5ch;
  text-align: center;
}

/* Peek affordance: a faint offset card edge behind the current poster's right
   side, hinting the next film is stacked behind it. Only when more remain. */
.atlas-current-stop.atlas-has-next .atlas-stop-poster {
  position: relative;
}
.atlas-current-stop.atlas-has-next .atlas-stop-poster::after {
  content: "";
  position: absolute;
  top: 6px;
  bottom: 6px;
  right: -8px;
  width: 10px;
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  background: var(--cream-field);
  border: 1px solid var(--border);
  border-left: none;
  z-index: -1;
  pointer-events: none;
}

/* Recommended film's title rendered as an open-the-card link (reuses the
   slide-in card). Reads as the same display heading, gains a hover accent. */
.atlas-stop-title-link {
  display: inline;
  padding: 0;
  background: none;
  border: none;
  text-align: left;
  cursor: pointer;
  color: inherit;
  font: inherit;
  transition: color var(--dur-fast) var(--ease-out);
}
.atlas-stop-title-link:hover { color: var(--color-accent); }
.atlas-stop-title-link:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

/* A cited film named inline in the grounded answer — a text link into its card,
   marked with a subtle accent underline so it reads as tappable prose. */
.atlas-answer-link {
  padding: 0;
  background: none;
  border: none;
  cursor: pointer;
  font: inherit;
  color: var(--color-base);
  text-decoration: underline;
  text-decoration-color: var(--color-accent);
  text-underline-offset: 2px;
  transition: color var(--dur-fast) var(--ease-out);
}
.atlas-answer-link:hover { color: var(--color-accent); }
.atlas-answer-link:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  .atlas-carousel-btn,
  .atlas-stop-title-link,
  .atlas-answer-link { transition: none; }
}

.atlas-opt-hint {
  font-family: var(--font-ui); font-size: var(--text-xs); color: var(--cream-dim);
  margin-left: auto; white-space: nowrap;
}
.atlas-opt { justify-content: space-between; flex-direction: row; align-items: center; flex-wrap: wrap; }
