/* ==========================================================================
   WAIVY UI KIT — the waivy.chat look, portable.
   iMessage-style chat surface: sand/ink palette, glass bubbles, an ocean "border
   beam" that rings the composer and the typing pill, animated typing dots, a
   Google-AI-Mode composer that springs open on focus, and a query that floats up
   on the right.

   Drop-in: <link rel="stylesheet" href="waivy-ui.css"> + waivy-ui.js.
   Everything is namespaced `wv-` / `lp-`. Theme via <html data-theme="dark">.
   ========================================================================== */

/* ── Design tokens (light = default; dark overrides below) ───────────────── */
:root {
  --font-system: "Instrument Sans", -apple-system, BlinkMacSystemFont, "SF Pro Text", "SF Pro Display", "Helvetica Neue", system-ui, sans-serif;
  --font-serif: "Source Serif 4", Georgia, "Iowan Old Style", serif;
  --transition-fast: 0.15s cubic-bezier(0.4, 0, 0.2, 1);

  /* Palette — ADL: white canvas, warm ink (the Answer Design Language look) */
  --bg-app: #ffffff;
  --bg-app-gradient: #ffffff;
  --color-ink: #1f2126;
  --color-sand: #f8f7f3;
  --text-primary: #1f2126;          /* ink */
  --text-secondary: #5a574d;        /* secondary text / asides */
  --text-tertiary: #9a968a;         /* meta / numbers / axis */
  --text-inverse: #ffffff;
  --accent-color: #1f2126;
  --wv-table-header: #1f2126;
  --wv-accent: #2f5fc4;   /* the dark blue of the input glow — kept for the highlight pill + focus glow */
  --border-color: #eceae2;
  --divider: #eceae2;

  /* ADL role tokens */
  --wv-hairline: #eceae2;
  --wv-rule-strong: #dedacd;
  --wv-hl-tint: color-mix(in srgb, var(--wv-accent) 10%, transparent);   /* concise answer highlight */
  --wv-chip-tint: #f1efe8;          /* source chip / query pill tint (warm cream) */
  --wv-panel-tint: #f8f7f3;         /* chart / code / data panel */
  --wv-up: #1b9a4a;
  --wv-down: #c4442a;
  --wv-link-underline: #c9c4b4;     /* deepen / masked-link underline */

  /* Answer composition — one scale shared by prose, lists and data blocks. */
  --wv-answer-lead-size: 17px;
  --wv-answer-body-size: 15.5px;
  --wv-answer-data-size: 14px;
  --wv-answer-line: 24px;
  --wv-answer-section-gap: 24px;
  --wv-answer-block-gap: 8px;
  --wv-chat-column: 560px;
  /* One shared heading-to-content rhythm for markdown sections and rich-card labels. */
  --wv-answer-heading-content-gap: 8px;

  /* Bubbles */
  --bg-bubble-user: #1f2126;        /* outbound (right) — ink query pill */
  --bg-bubble-user-text: #f7f3ec;
  --imsg-bubble-radius: 18px;
  --imsg-bubble-grey: #f8f7f3;      /* mono card / panel surface on the white canvas */
  --imsg-bubble-grey-text: #1f2126;

  /* Logo tint */
  --waivy-slate-dark: #3d4458;
  --waivy-slate-soft: #989aae;

  /* Composer surface (opaque so the glow only shows at the 2px overhang) */
  --lp-composer-bg: #fbfaf7;

  --hdr-clearance: calc(58px + env(safe-area-inset-top));
  --dock-clearance: calc(118px + env(safe-area-inset-bottom));
}
[data-theme="dark"] {
  --bg-app: #0f1a26;
  --bg-app-gradient: radial-gradient(ellipse at top, #1a2738 0%, #0f1a26 55%, #060c14 100%);
  --color-ink: #e8edf3;
  --color-sand: #0e1822;
  --text-primary: #e8edf3;
  --text-secondary: #8e9aa8;
  --text-tertiary: #5d6776;
  --text-inverse: #0e1822;
  --accent-color: #e8edf3;
  --wv-table-header: var(--text-primary);
  --wv-accent: #4079e0;   /* brighter glow-blue for contrast on dark */
  --border-color: rgba(255, 255, 255, 0.08);
  --divider: rgba(255, 255, 255, 0.1);

  /* ADL role tokens */
  --wv-hairline: var(--divider);
  --wv-rule-strong: rgba(255, 255, 255, 0.22);
  --wv-hl-tint: color-mix(in srgb, var(--wv-accent) 26%, transparent);
  --wv-chip-tint: color-mix(in srgb, var(--wv-accent) 16%, transparent);
  --wv-panel-tint: color-mix(in srgb, var(--text-primary) 8%, transparent);
  --wv-up: #1a9e63;
  --wv-down: #d64545;

  --bg-bubble-user: #e8edf3;        /* dark: user bubble inverts to warm light */
  --bg-bubble-user-text: #0e1822;
  --imsg-bubble-grey: #2a3340;
  --imsg-bubble-grey-text: #e8edf3;
  --waivy-slate-dark: #989aae;
  --lp-composer-bg: #1c2733;
}

/* ── App shell — the DOCUMENT scrolls (google.com-style); header + dock fixed ── */
html { height: auto; min-height: 100%; overflow: visible; overscroll-behavior-y: contain; }
body {
  height: auto; min-height: 100%; overflow: visible; max-width: 100%;
  margin: 0; padding: 0; display: block;
  /* Solid background (iMessage-authentic) so the bubble-tail cutout blends everywhere.
     A gradient made the small tail cutout sample its bright center → a grey blob. */
  background: var(--bg-app);
  font-family: var(--font-system); color: var(--text-primary);
  -webkit-font-smoothing: antialiased;
}
.wv-app { min-height: 100dvh; overflow-x: clip; }   /* bubble tails poke past the edge */

/* ── Header — frosted glass, fixed over the scrolling thread ─────────────────
   Translucent + blurred (Safari-style): the thread stays faintly visible
   scrolling behind the bar instead of being hidden by an opaque fill. */
.lp-hdr {
  position: fixed; top: 0; left: 0; right: 0; z-index: 20;
  display: flex; align-items: center; justify-content: space-between;
  padding: calc(10px + env(safe-area-inset-top)) 16px 10px;
  background: color-mix(in srgb, var(--bg-app) 70%, transparent);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  backdrop-filter: saturate(180%) blur(20px);
  border-bottom: 1px solid color-mix(in srgb, var(--divider) 50%, transparent);
}
/* No backdrop-filter support (older browsers) → keep it opaque so the
   wordmark/profile never sit on unreadable see-through content. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .lp-hdr { background: var(--bg-app); }
}
.lp-mark { height: 20px; width: auto; color: var(--waivy-slate-dark); }
.lp-brand { display: inline-flex; align-items: center; gap: 8px; }
.lp-wordmark { font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 14px; font-weight: 500; letter-spacing: -0.01em; color: var(--text-primary); line-height: 1; }
.lp-hdr-actions {
  display: inline-flex; align-items: center; gap: 8px;
  transition: opacity 0.25s ease, transform 0.25s ease;
}
/* Scoped to .lp-getstarted (was the whole nav): the compare toggle stays
   visible/clickable after a chat starts. Transition moved onto the child. */
body.hdr-hidden .lp-hdr-actions .lp-getstarted { opacity: 0; transform: translateY(-10px); pointer-events: none; transition: opacity 0.25s ease, transform 0.25s ease; }
.lp-getstarted {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--font-system); font-size: 0.86rem; font-weight: 600;
  color: var(--text-primary); background: var(--imsg-bubble-grey);
  border: none; border-radius: 999px; padding: 7px 14px;
  text-decoration: none; cursor: pointer; white-space: nowrap;
  transition: transform var(--transition-fast), opacity var(--transition-fast);
}
.lp-getstarted:hover { opacity: 0.92; }
.lp-getstarted:active { transform: scale(0.97); }
.lp-getstarted.is-authed { background: color-mix(in srgb, var(--waivy-slate-dark) 8%, var(--imsg-bubble-grey)); }
.lp-gs-label { display: inline-flex; align-items: center; gap: 6px; }
.lp-gs-dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: #34c759; box-shadow: 0 0 0 2px color-mix(in srgb, #34c759 25%, transparent);
  flex-shrink: 0;
}
.lp-gs-logos { display: inline-flex; align-items: center; gap: 5px; }
.lp-gs-logo { width: 16px; height: 16px; display: block; }

/* ── Thread ───────────────────────────────────────────────────────────────── */
.lp-scroll { padding: var(--hdr-clearance) 14px var(--dock-clearance); font-family: var(--font-system); overflow-anchor: none; }
.lp-thread { width: 100%; max-width: var(--wv-chat-column); min-width: 0; margin: 0 auto; box-sizing: border-box; }

/* ── Bubble rows — iMessage geometry ─────────────────────────────────────── */
.lp-turn { max-width: 100%; min-width: 0; box-sizing: border-box; padding-top: 8px; }   /* breathing room above each turn's question (hides the prior turn behind the header when pinned) */
/* A small gap AFTER each finished conversation so the previous turn's last bubble tucks fully
   behind the header instead of peeking under it. Only non-last turns get it (renders after the
   restore, and the restore's height math accounts for it, so the current question doesn't move). */
.lp-turn:not(:last-child) { margin-bottom: 40px; }
/* Graceful send exits: prior turns fade + rise out (0.2s) before they're hidden — no hard
   cut while the fresh question rises. Restored history fades back in softly above it. */
.lp-turn { transition: opacity 0.2s ease, transform 0.2s ease; }
.lp-turn-exit { opacity: 0 !important; transform: translateY(-10px); }
.lp-turn-restore { animation: chat-fade-in 0.3s ease both; }
.lp-row { display: flex; max-width: 100%; min-width: 0; box-sizing: border-box; padding: 0 4px; margin: 1px 0; }
.lp-row.user { justify-content: flex-end; }
.lp-row.waivy { justify-content: flex-start; }
.lp-row + .lp-row.user, .lp-row + .lp-row.waivy { margin-top: 5px; }        /* between a reply's own stacked bubbles */
.lp-row.user + .lp-row.waivy, .lp-row.waivy + .lp-row.user { margin-top: 16px; }  /* between query ↔ reply */
.lp-fly { position: fixed; z-index: 30; margin: 0; padding: 0; pointer-events: none; will-change: transform; }

.lp-bubble {
  max-width: 78%; min-width: 0; box-sizing: border-box; padding: 8px 12px;
  font-size: 0.95rem; line-height: 1.28; letter-spacing: -0.002em;
  white-space: pre-wrap; word-wrap: break-word; overflow-wrap: anywhere;
  animation: chat-fade-in 0.5s cubic-bezier(0.34, 1.28, 0.64, 1) both;
  animation-delay: calc(var(--stagger, 0) * 60ms);
  position: relative; border-radius: var(--imsg-bubble-radius);
  isolation: isolate;   /* own stacking context so the z-index:-1 tail nub sits behind the bubble but above the page */
}
.lp-bubble a { color: #0a7cff; text-decoration: none; font-weight: 600; word-break: break-word; }
/* ADL masked links: ink + subtle underline (like deepen links), not iMessage blue.
   `a.lp-link` ties `.lp-bubble a` on specificity and wins by order. */
a.lp-link { font-weight: 600; color: var(--text-primary); text-decoration: underline; text-decoration-color: var(--wv-rule-strong); text-underline-offset: 2px; text-decoration-thickness: 1.5px; }

/* Inline per-claim citation — the server resolves a model `[n]` marker into a masked link whose
   label is just the number, and fmt() classes a digit-only label as this. Google AI Mode averages
   two per answer; ours must read as a footnote mark, never as body text, so it rides above the
   baseline at a smaller size and takes no underline. `vertical-align: super` alone would stretch
   the line box, so the line-height is pinned to 0. */
a.lp-cite {
  display: inline; padding: 0 .28em; margin-left: .15em;
  font-size: .68em; line-height: 0; vertical-align: super; font-weight: 600;
  text-align: center; text-decoration: none; border-radius: .5em;
  color: var(--text-secondary, #666); background: var(--wv-rule, rgba(0,0,0,.06));
  transition: background .15s ease, color .15s ease; white-space: nowrap;
}
a.lp-cite:hover { color: var(--text-primary); background: var(--wv-rule-strong, rgba(0,0,0,.12)); }
/* Two markers on one sentence sit flush; keep them from reading as a single 2-digit number. */
a.lp-cite + a.lp-cite { margin-left: .2em; }
.lp-cite-cluster {
  display: inline-flex; align-items: baseline; gap: .18em; margin-left: .15em; padding: .08em .34em;
  border-radius: .55em; background: var(--wv-rule, rgba(0,0,0,.06)); color: var(--text-secondary, #666);
  font-size: .68em; line-height: 1; vertical-align: super; white-space: nowrap;
}
.lp-cite-cluster a.lp-cite { margin: 0; padding: 0; font-size: 1em; line-height: 1; vertical-align: baseline; background: transparent; border-radius: 0; }
.lp-cite-cluster a.lp-cite + a.lp-cite { margin-left: 0; }
.lp-cite-cluster a.lp-cite + a.lp-cite::before { content: ","; margin-right: .18em; color: var(--text-tertiary); }
.lp-bubble a:active { opacity: 0.6; }
/* Full-width card divider (from a ━/─ rule line) — adapts to the bubble, never overflows. */
.lp-rule { display: block; height: 0; border-top: 1.5px solid currentColor; opacity: 0.18; margin: 7px 0; }
.lp-rule-heavy { border-top-width: 2px; opacity: 0.32; }
.lp-row.user .lp-bubble { background: var(--bg-bubble-user); color: var(--bg-bubble-user-text); }
/* ADL: the assistant answer is FLAT on the canvas — no grey response bubble. The lead,
   the italic aside, and the `##` headings render as plain text; only mono cards
   (panels / bar charts) keep a surface. The query pill (user, above) stays a pill. */
.lp-row.waivy .lp-bubble { color: var(--imsg-bubble-grey-text); font-size: var(--wv-answer-body-size); line-height: var(--wv-answer-line); }
.lp-row.waivy .lp-bubble:not(.lp-mono) {
  background: transparent; padding: 2px 2px; border-radius: 0; max-width: 100%;
}
.lp-row.waivy .lp-bubble.lp-mono { background: var(--imsg-bubble-grey); }
/* The streaming glow ring is a rounded-rect around the grey bubble — on flat prose it
   would float as a rectangle around the text, so drop it there (mono cards keep it). */
.lp-row.waivy .lp-bubble:not(.lp-mono).lp-glow::before { display: none; }
.lp-bubble-img { max-width: 200px; border-radius: 12px; display: block; }
/* Channel-handoff action buttons — iMessage / WhatsApp deep links + web login under a bubble.
   Selectors are scoped under .lp-actions (0,2,0) so they beat `.lp-bubble a` (0,1,1) — otherwise
   the link color would override the white button text. */
.lp-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 11px; }
.lp-actions .lp-action {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--font-system); font-size: 0.9rem; font-weight: 600; letter-spacing: -0.005em;
  color: #fff; background: #0a7cff; border-radius: 999px; padding: 8px 15px;
  text-decoration: none; white-space: nowrap; -webkit-tap-highlight-color: transparent;
  transition: transform 0.12s ease, filter 0.12s ease;
}
.lp-actions .lp-action:active { transform: scale(0.95); filter: brightness(0.92); }
.lp-actions .lp-action-wa { background: #25d366; color: #fff; }                     /* WhatsApp green */
.lp-actions .lp-action-web { background: #1c1c1e; color: #fff; }                    /* web login */
.lp-actions .lp-action-logout { background: #1c1c1e; color: #fff; }                 /* web logout */
.lp-actions .lp-action-ghost { background: transparent; color: #0a7cff; box-shadow: inset 0 0 0 1.5px currentColor; }
.lp-actions .lp-action-ic { display: inline-flex; align-items: center; line-height: 1; }
.lp-actions .lp-action-ic svg { display: block; flex-shrink: 0; }

/* ── Map card (ChatGPT-style): the MAP on top (tap → full-screen), the clustered LIST below ── */
.lp-mapcard {
  width: 100%; max-width: 560px; border-radius: 18px; overflow: hidden;
  background: var(--imsg-bubble-grey); border: 1px solid var(--border-color);
  animation: chat-fade-in 0.5s cubic-bezier(0.34, 1.28, 0.64, 1) both;
  display: flex; flex-direction: column;   /* map first, then the list below it */
}
.lp-mapcard .lp-map-live { order: 0; }
.lp-mapcard .lp-place-list { order: 1; }
.lp-mapcard .lp-map-live, .lp-mapcard .lp-map-wrap { height: 240px; }
.lp-mapcard .lp-map-img { height: 240px; object-fit: cover; }
.lp-map-wrap { display: block; position: relative; text-decoration: none; background: var(--divider, #e6e3db); }
.lp-map-img { display: block; width: 100%; height: auto; cursor: pointer; background: #e6e3db; }
.lp-mapcard-wrap { display: block; max-width: 560px; width: 100%; min-width: 0; box-sizing: border-box; }
/* ⤢ expand affordance, top-right of the inline map */
.lp-map-expand {
  position: absolute; top: 10px; right: 10px; z-index: 2; width: 34px; height: 34px;
  display: flex; align-items: center; justify-content: center; padding: 0; cursor: pointer;
  border: none; border-radius: 10px; color: var(--text-primary);
  background: color-mix(in srgb, var(--imsg-bubble-grey) 82%, transparent);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  box-shadow: 0 1px 4px rgba(0,0,0,0.18);
}
.lp-map-expand:active { transform: scale(0.94); }
/* Category header inside the clustered place list (editorial style bucket) */
.lp-map-group {
  font-family: var(--font-system); font-size: 0.7rem; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--text-tertiary);
  padding: 14px 14px 6px; border-top: 1px solid var(--divider);
}
.lp-place-list > .lp-map-group:first-child { border-top: none; padding-top: 10px; }

/* ── Editorial guide — GOOGLE-AI-MODE writeup on the canvas (separate from the map card, no
   background): category header, then venue rows (thumb + name + rating + meta + description). ── */
.lp-guide { padding: 4px 2px 12px; margin-top: 10px; background: transparent; font-family: var(--font-system); min-width: 0; max-width: 100%; box-sizing: border-box; }
.lp-guide-item, .lp-guide-desc, .lp-guide-rowmain, .lp-guide-metaline, .lp-guide-copy { min-width: 0; overflow-wrap: break-word; word-break: break-word; }
.lp-guide-group { padding: 0; }
.lp-guide-head {
  display: flex; align-items: center; gap: 8px; padding: 22px 2px 12px;   /* clear air below the header */
  font-size: 1.18rem; font-weight: 700; color: var(--text-primary);
}
.lp-guide-group:first-child .lp-guide-head { padding-top: 6px; }
.lp-guide-emoji { font-size: 1.16rem; line-height: 1; }
.lp-guide-item { padding: 12px 2px; }   /* spacing, NO divider rules */
.lp-guide-row { display: grid; grid-template-columns: 104px minmax(0, 1fr); gap: 16px; align-items: start; text-decoration: none; cursor: pointer; }
.lp-guide-thumb { width: 104px; height: 104px; border-radius: 14px; object-fit: cover; flex: none; background: var(--divider); }
.lp-guide-rowmain { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.lp-guide-copy { grid-column: 1 / -1; margin-top: -2px; }
.lp-guide-name {
  font-size: 1.06rem; font-weight: 600; color: var(--text-primary); text-decoration: underline;
  text-underline-offset: 2px; text-decoration-color: color-mix(in srgb, var(--text-primary) 28%, transparent);
}
.lp-guide-row:hover .lp-guide-name { text-decoration-color: var(--text-primary); }
.lp-guide-metaline { font-size: 0.92rem; line-height: 1.35; color: var(--text-secondary); margin-top: 2px; }
.lp-guide-rating { color: var(--text-primary); }
.lp-guide-star { color: #f5a623; }
.lp-guide-open { color: var(--wv-up, #12a150); font-weight: 600; }
.lp-guide-closed { color: var(--wv-down, #d1483a); font-weight: 600; }
.lp-guide-desc { font-size: 0.98rem; line-height: 1.5; color: var(--text-primary); margin-top: 10px; }
.lp-guide-callout { margin-top: 8px; }
.lp-guide-callout b { font-weight: 700; }

@media (max-width: 560px) {
  .lp-guide-row { grid-template-columns: 88px minmax(0, 1fr); gap: 12px; }
  .lp-guide-thumb { width: 88px; height: 88px; border-radius: 12px; }
}

/* ── Sources — Perplexity-style citation grid (server-built) ── */
.lp-sources-wrap { display: block; width: 100%; max-width: 560px; min-width: 0; box-sizing: border-box; margin-top: 24px; padding-top: 16px; border-top: 1px solid var(--wv-hairline); }
.lp-sources-label {
  display: block; font-family: var(--font-system); font-size: 0.78rem; letter-spacing: 0.05em;
  text-transform: uppercase; color: var(--text-secondary); margin: 2px 0 2px 2px;
}
.lp-sources { display: grid; width: 100%; max-width: 100%; min-width: 0; box-sizing: border-box; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 18px; }
.lp-source {
  display: flex; gap: 12px; align-items: flex-start; text-decoration: none;
  width: 100%; max-width: 100%; min-width: 0; box-sizing: border-box;
  min-height: 88px; padding: 11px 2px; border-top: 1px solid var(--divider);
}
.lp-source-cite {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; margin-top: 1px; border-radius: 50%;
  font: 650 10px/1 var(--font-system); color: var(--text-secondary); background: var(--wv-chip-tint);
}
.lp-source:nth-child(-n+2) { border-top: none; }
.lp-source-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; justify-content: space-between; }
.lp-source-title {
  font-family: var(--font-system); font-size: 0.94rem; font-weight: 600; line-height: 1.32;
  color: var(--text-primary); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.lp-source:hover .lp-source-title { text-decoration: underline; text-underline-offset: 2px; }
.lp-source-meta { font-family: var(--font-system); font-size: 0.74rem; color: var(--text-secondary); display: flex; align-items: center; gap: 6px; min-width: 0; }
.lp-source-pub { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lp-source-fav { width: 16px; height: 16px; border-radius: 50%; flex: none; background: var(--divider); }
.lp-source-thumb { width: min(74px, 34%); height: auto; aspect-ratio: 1 / 1; border-radius: 12px; object-fit: cover; flex: 0 1 74px; min-width: 0; background: var(--divider); }
.lp-source-thumb.is-logo { object-fit: contain; padding: 8px; box-sizing: border-box; }
.lp-source-disclosure:not(.is-expanded) .lp-source-extra { display: none; }
.lp-source-more {
  display: block; width: 100%; margin: 2px 0 0; padding: 10px 2px 2px;
  border: 0; border-top: 1px solid var(--divider); background: transparent;
  color: var(--text-primary); font: 600 13px/20px var(--font-system); text-align: left;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.lp-source-more::after { content: " ↓"; color: var(--text-tertiary); }
.lp-source-disclosure.is-expanded .lp-source-more::after { content: " ↑"; }
.lp-source-more:hover { color: var(--wv-accent); }
.lp-source-more:focus-visible { outline: 2px solid color-mix(in srgb, var(--wv-accent) 55%, transparent); outline-offset: 2px; border-radius: 4px; }
@media (max-width: 560px) {
  .lp-sources { grid-template-columns: 1fr; }
  .lp-source:nth-child(2) { border-top: 1px solid var(--divider); }
  .lp-source-thumb { width: 62px; height: 62px; }
}

/* Per-entity comparison cards ("X vs Y" breakdown) — image/price/rating header + bold bullets. */
.lp-bd-wrap { display: block; max-width: 640px; margin: 2px 0; }
.lp-bd-label {
  font-family: var(--font-system); font-size: 0.68rem; letter-spacing: 0.07em;
  text-transform: uppercase; color: var(--text-tertiary); margin: 2px 0 8px 2px;
}
.lp-bd-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 26px 40px; align-items: start; }
.lp-bd-foot { margin-top: 16px; }   /* source chip folded onto the last breakdown */
/* 3+ picks become a vertical shopping list — a 2×2 grid with an empty 4th slot reads
   broken, and stacked rows glance better on desktop. Exactly-2 (X vs Y) stays side-by-side. */
.lp-bd-grid:has(> :nth-child(3)) { grid-template-columns: 1fr; gap: 22px; }
.lp-bd-card { padding: 0; }
.lp-bd-head { display: flex; gap: 12px; align-items: flex-start; }
.lp-bd-thumb { width: 60px; height: 60px; border-radius: 12px; object-fit: cover; flex: none; background: var(--divider); cursor: zoom-in; }
.lp-bd-headtext { flex: 1; min-width: 0; }
.lp-bd-name { font-family: var(--font-system); font-size: 1.05rem; font-weight: 600; line-height: 1.25; color: var(--text-primary); }
.lp-bd-priceline {
  font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.82rem;
  margin-top: 3px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.lp-bd-price { color: var(--wv-up); font-weight: 700; }
.lp-bd-was { color: var(--text-tertiary); text-decoration: line-through; }
.lp-bd-rating { color: var(--text-secondary); }
.lp-bd-meta {
  font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.72rem;
  color: var(--text-tertiary); margin-top: 2px;
}
.lp-bd-bullets { list-style: none; margin: 11px 0 0; padding: 0; }
.lp-bd-bullet {
  font-family: var(--font-system); font-size: 0.9rem; line-height: 1.5; color: var(--text-secondary);
  padding-left: 16px; position: relative; margin-top: 7px;
}
.lp-bd-bullet:first-child { margin-top: 0; }
.lp-bd-bullet::before { content: ""; position: absolute; left: 2px; top: 0.52em; width: 5px; height: 5px; border-radius: 50%; background: var(--wv-accent); }
.lp-bd-bullet b, .lp-bd-bullet strong { color: var(--text-primary); font-weight: 700; }
@media (max-width: 560px) {
  .lp-bd-grid { grid-template-columns: 1fr; gap: 22px; }
  .lp-bd-thumb { width: 52px; height: 52px; }
}

/* ── Rich answer blocks (Google-AI-Mode restyle) ──────────────────────────────
   Inline: ==highlight== pill + ##/### section headers. Blocks: real tables/lists,
   rich feed rows, CSS bar charts. Flat (no grey bubble box), like sources/breakdown. */
mark.lp-hl {
  background: var(--wv-hl-tint);
  color: inherit; font-weight: 700;   /* the highlighted fact is always bold (ADL) */
  border-radius: 4px; padding: 0 0.16em; margin: 0;
  box-shadow: inset 0 -1px 0 color-mix(in srgb, var(--wv-accent) 18%, transparent);
  max-width: 100%; white-space: normal; overflow-wrap: anywhere; word-break: normal;
  -webkit-box-decoration-break: clone; box-decoration-break: clone;
}
/* `## H` / `### H` prose lines. The bubble is pre-wrap — fmt() swallows the newlines,
   so the block display + margins supply the section rhythm. */
.lp-h2 { display: block; font-size: 19px; font-weight: 720; line-height: 25px; letter-spacing: -0.015em; color: var(--text-primary); margin: var(--wv-answer-section-gap) 0 var(--wv-answer-heading-content-gap); }
.lp-h3 { display: block; font-size: 19px; font-weight: 720; line-height: 25px; letter-spacing: -0.015em; color: var(--text-primary); margin: var(--wv-answer-section-gap) 0 var(--wv-answer-heading-content-gap); }
.lp-heading-emoji {
  display: inline-flex; width: 25px; height: 25px; align-items: center; justify-content: center;
  margin-right: 8px; border-radius: 8px; background: var(--wv-chip-tint);
  font-size: 14px; line-height: 1; font-style: normal; vertical-align: -3px;
}
.lp-bubble .lp-h2:first-child, .lp-bubble .lp-h3:first-child { margin-top: 0; }
/* …so a bubble that OPENS with a section header is a new SECTION — give it air at the row
   level instead (the default inter-bubble gap is only 5px, which read cramped). */
.lp-row.waivy:has(.lp-h2:first-child), .lp-row.waivy:has(.lp-h3:first-child) { margin-top: var(--wv-answer-section-gap); }
.lp-pos { color: var(--wv-up); }
.lp-neg { color: var(--wv-down); }

/* Shared rich-card frame: a single answer gutter for tables, lists and prose. */
.lp-rich { display: block; width: calc(100% - 4px); max-width: 100%; margin: 0 2px; box-sizing: border-box; font-family: var(--font-system); }
.lp-rich-label {
  font-family: var(--font-system); font-size: 19px; font-weight: 720; line-height: 25px; letter-spacing: -0.015em;
  color: var(--text-primary); margin: 0 0 var(--wv-answer-heading-content-gap);
}
.lp-rich-ic { margin-right: 5px; }
.lp-rich-foot { font-size: 0.72rem; color: var(--text-tertiary); font-style: italic; margin: 7px 2px 0; }
.lp-rich-freshness { font-style: normal; }
.lp-rich-freshness a { color: inherit; text-decoration: underline; text-decoration-color: color-mix(in srgb, currentColor 45%, transparent); text-underline-offset: 2px; }
.lp-rich-freshness a:hover { color: var(--wv-accent); }
.lp-rich-chipline { margin: 9px 0 0; }

/* Real HTML tables — comparisons, ranked records, box scores. */
.lp-table-scroll { overflow-x: visible; }
.lp-rich-kind-table:not(.lp-rich-finance) {
  width: 100%; margin-left: 0; margin-right: 0; padding: 12px 14px 10px;
  border: 1px solid var(--wv-hairline); border-radius: 14px; background: var(--wv-panel-tint);
}
/* A MARKDOWN PIPE TABLE written inside a prose block (ANSWER CONTRACT v5). The answer bubble is
   `white-space: pre-wrap` so its newlines survive; a table inheriting that would keep the literal
   newlines between cells and render every row double-height. It also needs its own vertical rhythm,
   since unlike a rich card it has no .lp-rich wrapper supplying margins. */
.lp-bubble .lp-table-inline, .lp-table-inline { white-space: normal; display: block; margin: var(--wv-answer-block-gap) 0 0; }
.lp-table-inline > table { white-space: normal; }
/* Many-column tables are now possible (v5 removed the 4-column cap), and a fixed layout squeezes
   them unreadably on a phone. Scroll the table instead of the page — the body must never scroll
   sideways. */
@media (max-width: 560px) {
  .lp-table-inline { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .lp-table-inline > table { table-layout: auto; min-width: 100%; }
}
.lp-table { border-collapse: collapse; width: 100%; font-size: var(--wv-answer-data-size); line-height: 20px; table-layout: fixed; }
.lp-table th, .lp-table td { text-align: left; padding: 8px 12px 8px 0; border-top: 1px solid var(--wv-hairline); vertical-align: top; }
.lp-table th:last-child, .lp-table td:last-child { padding-right: 0; }
.lp-table thead th {
  border-top: none; font-size: 11px; letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--wv-table-header); font-weight: 700; white-space: normal; overflow-wrap: anywhere;
}
/* The first header cell never wraps mid-word — a many-column line-score squeezes it to
   2ch and ships "TEA M" (format audit sports probe, 2026-07-31). */
.lp-table thead th:first-child { white-space: nowrap; overflow-wrap: normal; }
.lp-table tbody th.lp-th-row { font-weight: 600; color: var(--text-primary); }
.lp-table td { color: var(--text-secondary); }
.lp-table .lp-table-entity { color: var(--text-primary); font-weight: 600; }
.lp-table-ranked tbody tr:first-child .lp-table-entity,
.lp-table-ranked tbody tr:first-child td.lp-td-num:last-child { color: var(--text-primary); font-weight: 700; }
.lp-table td b { color: var(--text-primary); font-weight: 700; }
/* Cells wrap at word boundaries by default (anywhere caused mid-word breaks in squeezed
   fixed-layout columns); only long unbreakable tokens wrap, and numerics stay nowrap. */
.lp-table th, .lp-table td { overflow-wrap: break-word; }
.lp-table td.lp-td-num, .lp-table th.lp-td-num { font-variant-numeric: tabular-nums; white-space: nowrap; overflow-wrap: normal; }
.lp-table td.lp-td-num, .lp-table thead th.lp-td-num { text-align: left; }
.lp-table-disclosure:not(.is-expanded) .lp-table-row-extra { display: none; }
.lp-table-more {
  display: block; width: 100%; margin: 0; padding: 10px 0 2px;
  border: 0; border-top: 1px solid var(--wv-hairline); background: transparent;
  color: var(--text-primary); font: 600 13px/20px var(--font-system); text-align: left;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.lp-table-more::after { content: " ↓"; color: var(--text-tertiary); }
.lp-table-disclosure.is-expanded .lp-table-more::after { content: " ↑"; }
.lp-table-more:hover { color: var(--wv-accent); }
.lp-table-more:focus-visible { outline: 2px solid color-mix(in srgb, var(--wv-accent) 55%, transparent); outline-offset: 2px; border-radius: 4px; }
.lp-table-more:active { opacity: 0.65; }
/* Team crest before a team-name cell (server-attached icons map — championship tables). */
.lp-team-ic {
  width: 18px; height: 18px; object-fit: contain; vertical-align: -4px;
  margin-right: 7px; display: inline-block; border-radius: 3px;
}
.lp-team-cell { display: inline-flex; align-items: center; gap: 7px; white-space: nowrap; }
.lp-team-cell .lp-team-ic { margin-right: 0; flex: none; }
.lp-table thead th .lp-team-ic { width: 15px; height: 15px; vertical-align: -3px; margin-right: 5px; }

/* Real HTML lists — accent bullets / counters, bold lead labels, nested sub-tier.
   Google-AI-Mode glanceability: hanging indent + real air between items (each bullet
   reads as its own row, wrapped lines never fall back to the left margin). */
.lp-rich-list { margin: 0; padding: 0 0 0 4px; list-style: none; }   /* nesting trimmed 8→4 per user (2026-07-31; was 14→8 before) */
.lp-rich-list > li {
  font-size: var(--wv-answer-body-size); line-height: var(--wv-answer-line); color: var(--text-primary);
  padding-left: 14px; position: relative; margin-top: var(--wv-answer-block-gap);
}
.lp-rich-list > li:first-child { margin-top: 0; }
/* A rich label and a markdown section header are the same semantic object. Keep the first
   bullet flush to the shared 8px heading rhythm rather than inheriting browser/list defaults. */
.lp-rich-label + .lp-rich-list { margin-top: 0; }
/* Round markers are DRAWN circles, not a glyph — a text "•" renders square-ish in some
   platform fonts (user report 2026-07-31); a CSS circle is round on every platform. */
ul.lp-rich-list > li::before { content: ""; position: absolute; left: 2px; top: 9.5px; width: 5px; height: 5px; border-radius: 50%; background: var(--text-secondary); }
/* A heading emitted as a list item (## …) reads as a header row, not a bulleted peer.
   counter-increment:none so it doesn't consume an ordinal in an ordered list (numbers skip). */
.lp-rich-list > li.lp-li-head { padding-left: 0; margin-top: 16px; counter-increment: none; }
.lp-rich-list > li.lp-li-head::before { content: none; }
.lp-rich-list > li.lp-li-head:first-child { margin-top: 0; }
.lp-rich-list > li.lp-li-head + li { margin-top: var(--wv-answer-heading-content-gap); }
ol.lp-rich-list { counter-reset: lpli; }
ol.lp-rich-list > li { counter-increment: lpli; padding-left: 28px; }
ol.lp-rich-list > li::before {
  content: counter(lpli) "."; position: absolute; left: 2px;
  color: var(--text-primary); font-weight: 700; font-variant-numeric: tabular-nums;
}
.lp-rich-list b { color: var(--text-primary); font-weight: 700; }
/* Bullet lines living in PROSE (streaming provisional text, legacy answers) — MUST match
   .lp-rich-list > li EXACTLY (size / line-height / top margin), or the answer visibly re-settles
   when the provisional stream swaps to the final rich render at {t:"done"}. */
.lp-li { display: block; position: relative; padding-left: 14px; margin: var(--wv-answer-block-gap) 0 0 4px; font-size: var(--wv-answer-body-size); line-height: var(--wv-answer-line); }
.lp-li::before { content: ""; position: absolute; left: 2px; top: 9.5px; width: 5px; height: 5px; border-radius: 50%; background: var(--text-secondary); }
/* Streamed provisional ORDERED rows — mirror ol.lp-rich-list > li (number marker + hanging indent)
   so a "1." list doesn't re-settle from flush-left plain text into the final numbered list. */
.lp-li-num { display: block; position: relative; padding-left: 28px; margin: var(--wv-answer-block-gap) 0 0 4px; font-size: var(--wv-answer-body-size); line-height: var(--wv-answer-line); color: var(--text-primary); }
.lp-li-num::before { content: attr(data-num); position: absolute; left: 2px; color: var(--text-primary); font-weight: 700; font-variant-numeric: tabular-nums; }
/* Context qualification — compact and left-anchored to the claim it qualifies. */
.lp-aside {
  display: block; max-width: 640px; box-sizing: border-box; padding: 9px 12px;
  border-left: 3px solid color-mix(in srgb, var(--wv-accent) 36%, var(--wv-hairline));
  border-radius: 0 10px 10px 0; background: var(--wv-panel-tint);
  font-style: italic; font-size: 14px; color: var(--text-secondary); text-align: left;
  margin: 8px 0; line-height: 20px;
}
.lp-answer-lead .lp-aside { margin-top: 12px; }
/* aside → header gap equals lead → aside (the h2's 34px top margin used to triple it) */
.lp-aside + .lp-h2, .lp-aside + .lp-h3 { margin-top: 2px; }
.lp-row.waivy.lp-answer-row-aside { margin-top: var(--wv-answer-block-gap); margin-bottom: var(--wv-answer-block-gap); }
.lp-answer-row-aside .lp-aside { margin: 0; }
/* A standalone aside owns both sides of its rhythm. Keep the first section compact instead of
   stacking the generic section margin on top of the aside row's bottom gap. */
.lp-row.waivy.lp-answer-row-aside + .lp-row.waivy.lp-answer-row-section { margin-top: var(--wv-answer-block-gap); }
/* Closing "Would you like…" follow-up — compact separation from the final fact/list. */
.lp-closeq { display: block; margin-top: 12px; }
.lp-rich-sub { list-style: none; margin: 5px 0 0; padding: 0; }
.lp-rich-sub li { position: relative; padding-left: 16px; margin-top: 4px; font-size: 0.86rem; line-height: 1.45; }
.lp-rich-sub li::before { content: "–"; position: absolute; left: 2px; color: var(--text-tertiary); }

/* Rich feed — tag chip + wrapping serif headline + muted source · date. */
.lp-feed-item { display: block; padding: 9px 0; border-top: 1px solid var(--divider); }
.lp-feed-item:first-child { border-top: none; padding-top: 2px; }
.lp-feed-chip {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 0.72rem; font-weight: 600; color: var(--text-secondary);
  background: var(--wv-chip-tint);
  border-radius: 999px; padding: 2px 9px; margin-bottom: 4px;
}
.lp-feed-ic { line-height: 1; }
.lp-feed-title {
  display: block; font-family: var(--font-serif); font-size: 0.94rem; font-weight: 500;
  line-height: 1.32; color: var(--text-primary);
}
.lp-feed-meta { display: block; font-size: 0.72rem; color: var(--text-tertiary); margin-top: 3px; }

/* Google-AI-Mode news clusters — a section per beat: a lead article with a large image,
   then compact rows with a thumbnail. Every headline is a link (opens the in-app browser). */
.lp-news { display: block; }
.lp-news-context { display: flex; flex-wrap: wrap; align-items: center; gap: 5px; margin: -3px 0 10px; font-size: 0.78rem; line-height: 1.4; color: var(--text-secondary); }
.lp-news-sec { padding: 16px 0; border-top: 1px solid var(--divider); }
.lp-news-sec:first-child { border-top: none; padding-top: 2px; }
.lp-news-sec-h { font-family: var(--font-system); font-size: 0.84rem; font-weight: 700; letter-spacing: 0.01em; color: var(--text-primary); margin-bottom: 10px; }
.lp-news-lead { display: block; text-decoration: none; color: inherit; border-radius: 14px; overflow: hidden; }
.lp-news-lead-img { display: block; width: 100%; height: 172px; object-fit: cover; border-radius: 14px; background: var(--wv-chip-tint); }
.lp-news-lead.lp-news-noimg .lp-news-lead-img { display: none; }
.lp-news-lead-body { display: block; padding: 8px 2px 0; }
.lp-news-lead.lp-news-noimg .lp-news-lead-body { padding-top: 0; }
.lp-news-lead-title { display: block; font-family: var(--font-system); font-size: 1.06rem; font-weight: 650; line-height: 1.32; color: var(--text-primary); }
.lp-news-summary { display: -webkit-box; margin-top: 5px; overflow: hidden; -webkit-box-orient: vertical; -webkit-line-clamp: 2; font-family: var(--font-system); font-size: 0.86rem; font-weight: 400; line-height: 1.42; color: var(--text-secondary); }
.lp-news-more { margin-top: 4px; }
.lp-news-item { display: flex; gap: 10px; align-items: flex-start; padding: 10px 0; border-top: 1px solid var(--divider); text-decoration: none; color: inherit; }
.lp-news-item-body { flex: 1 1 auto; min-width: 0; }
.lp-news-item-title { display: block; font-family: var(--font-system); font-size: 0.92rem; font-weight: 600; line-height: 1.34; color: var(--text-primary); }
.lp-news-item .lp-news-summary { margin-top: 3px; font-size: 0.82rem; -webkit-line-clamp: 2; }
.lp-news-thumb { flex: none; width: 56px; height: 56px; border-radius: 10px; object-fit: cover; background: var(--wv-chip-tint); }
.lp-news-thumb-none { display: none; }
.lp-news-src { display: flex; align-items: center; gap: 5px; font-size: 0.78rem; line-height: 1.35; color: var(--text-secondary); margin-top: 5px; }
.lp-news-fav { width: 14px; height: 14px; border-radius: 3px; flex: none; }
.lp-news-badge { margin-left: auto; padding: 1px 6px; border-radius: 999px; color: var(--text-secondary); background: var(--wv-chip-tint); font-size: 0.68rem; font-weight: 650; }
.lp-news-lead:active .lp-news-lead-title, .lp-news-item:active .lp-news-item-title { color: var(--wv-accent); }

/* Trend sparkline (line/area charts) — Google-Finance-style SVG: direction-colored
   stroke + soft area fill + a meta row. Bars/heatmaps stay Unicode mono cards. */
.lp-spark { display: block; }
.lp-spark-up .lp-spark-svg, .lp-spark-up .lp-spark-delta { color: var(--wv-up); }
.lp-spark-down .lp-spark-svg, .lp-spark-down .lp-spark-delta { color: var(--wv-down); }
.lp-spark-svg { display: block; width: 100%; height: 72px; }
.lp-spark-line { fill: none; stroke: currentColor; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.lp-spark-fill { fill: currentColor; opacity: 0.10; stroke: none; }
.lp-spark-meta { display: flex; align-items: baseline; gap: 10px; margin-top: 7px; font-size: 0.85rem; color: var(--text-secondary); }
.lp-spark-meta b { font-size: 1.05rem; font-weight: 700; color: var(--text-primary); font-variant-numeric: tabular-nums; }
.lp-spark-delta { font-weight: 600; font-variant-numeric: tabular-nums; }
.lp-spark-range { color: var(--text-tertiary); font-variant-numeric: tabular-nums; }

/* Interactive Google map layered over the static image (which stays as the fallback). */
.lp-map-live { position: relative; min-height: 200px; }
.lp-map-canvas { position: absolute; inset: 0; display: none; }
.lp-map-live-on .lp-map-canvas { display: block; }
.lp-map-live-on .lp-map-fallback { visibility: hidden; }

/* ── Labeled name+rating map pins (AdvancedMarkerElement content) — inline + full-screen ── */
.lp-pin {
  display: inline-flex; align-items: center; gap: 5px; transform: translateY(-50%);
  padding: 4px 9px 4px 6px; border-radius: 999px; cursor: pointer; white-space: nowrap;
  background: #fff; color: #14110c; box-shadow: 0 2px 6px rgba(0,0,0,0.28);
  font-family: var(--font-system); font-size: 12.5px; font-weight: 600; line-height: 1;
  border: 1px solid rgba(0,0,0,0.06);
}
.lp-pin-badge { display: inline-flex; align-items: center; gap: 2px; font-weight: 700; }
.lp-pin-name { max-width: 130px; overflow: hidden; text-overflow: ellipsis; }
.lp-pin.sel { background: #14110c; color: #fff; box-shadow: 0 4px 12px rgba(0,0,0,0.4); z-index: 5; }

/* ── Full-screen interactive map (tap the inline ⤢) — map + featured card carousel ── */
body.lp-mapfull-open { overflow: hidden; }
.lp-mapfull { position: fixed; inset: 0; z-index: 58; background: var(--imsg-bg, #fff); animation: chat-fade-in 0.18s ease-out both; }
.lp-mapfull[hidden] { display: none; }
.lp-mapfull-canvas { position: absolute; inset: 0; }
.lp-mapfull-close {
  position: absolute; top: calc(12px + env(safe-area-inset-top)); left: 12px; z-index: 3;
  width: 40px; height: 40px; border-radius: 50%; border: none; cursor: pointer;
  display: flex; align-items: center; justify-content: center; color: #14110c;
  background: #fff; box-shadow: 0 2px 8px rgba(0,0,0,0.25);
}
.lp-mapfull-cards {
  position: absolute; left: 0; right: 0; bottom: calc(14px + env(safe-area-inset-bottom)); z-index: 3;
  display: flex; gap: 12px; overflow-x: auto; padding: 4px 16px; scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch; scrollbar-width: none;
}
.lp-mapfull-cards::-webkit-scrollbar { display: none; }
.lp-mfcard {
  scroll-snap-align: center; flex: 0 0 min(82%, 380px); display: flex; gap: 12px; text-align: left;
  padding: 12px; border-radius: 16px; border: 1px solid var(--border-color); cursor: pointer;
  background: var(--imsg-bubble-grey, #fff); box-shadow: 0 6px 22px rgba(0,0,0,0.14);
}
.lp-mfcard.sel { border-color: var(--wv-accent, #14110c); box-shadow: 0 8px 26px rgba(0,0,0,0.22); }
.lp-mfcard-thumb { width: 58px; height: 58px; border-radius: 12px; object-fit: cover; flex: none; background: var(--divider); }
.lp-mfcard-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.lp-mfcard-name { font-family: var(--font-system); font-size: 1rem; font-weight: 600; color: var(--text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lp-mfcard-meta { font-family: var(--font-system); font-size: 0.82rem; color: var(--text-secondary); }
.lp-mfcard-desc { font-family: var(--font-system); font-size: 0.86rem; color: var(--text-secondary); overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.lp-mfcard-open { color: var(--wv-up, #12a150); font-weight: 600; }
.lp-mfcard-closed { color: var(--wv-down, #d1483a); font-weight: 600; }

/* Inline photo strip for the top place — pictures first, then the map (Google-AI-Mode style). */
.lp-map-photos { display: flex; gap: 8px; overflow-x: auto; padding: 2px 2px 10px; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
.lp-map-photos::-webkit-scrollbar { display: none; }
.lp-map-photo { height: 130px; aspect-ratio: 4 / 3; border-radius: 12px; flex: none; object-fit: cover; background: #e6e3db; cursor: zoom-in; }

/* Image strip (Google-AI-Mode photo row under the lead) — horizontal, scrolls on overflow. */
.lp-strip-wrap { position: relative; display: block; width: 100%; max-width: 100%; min-width: 0; overflow: hidden; box-sizing: border-box; margin: 8px 0 10px; }
.lp-strip-photos { display: flex; width: 100%; max-width: 100%; min-width: 0; overflow-x: auto; box-sizing: border-box; gap: 8px; padding: 2px 2px 6px; -webkit-overflow-scrolling: touch; scrollbar-width: none; scroll-snap-type: x proximity; overscroll-behavior-inline: contain; }
.lp-strip-photos::-webkit-scrollbar { display: none; }
.lp-strip-photos[data-scroll-linked-images] { scroll-behavior: auto; }
.lp-strip-tile { flex: 0 0 calc((100% - 16px) / 3); min-width: 0; display: flex; flex-direction: column; line-height: normal; border-radius: 14px; overflow: hidden; background: var(--divider, #e6e3db); scroll-snap-align: start; box-shadow: 0 1px 0 color-mix(in srgb, var(--text-primary) 8%, transparent); }
.lp-strip-photo { width: 100%; height: auto; aspect-ratio: 4 / 3; border-radius: 14px; display: block; object-fit: cover; background: var(--divider, #e6e3db); }
@media (max-width: 560px) {
  .lp-strip-tile { flex-basis: min(72vw, 240px); }
  .lp-strip-wrap::after { content: ""; position: absolute; z-index: 2; top: 0; right: 0; bottom: 6px; width: 28px; pointer-events: none; background: linear-gradient(90deg, transparent, var(--bg-app)); }
}

/* ── Graceful image loading ───────────────────────────────────────────────────
   Result imagery starts hidden and fades in the instant it decodes — never a hard
   pop. Space is already reserved above (fixed height + aspect-ratio) so tiles don't
   reflow as photos arrive. `is-loaded` is added by the observer in waivy-ui.js
   (cached images are marked at once; a broken image is released too). Scoped to
   `img.` so the no-photo placeholder <span>s that share these classes stay visible;
   the visible placeholder lives on the tile CONTAINERS (opacity would hide an
   img's own background). */
img.lp-strip-photo, img.lp-map-photo, img.lp-sheet-photo, img.lp-map-img,
img.lp-place-thumb, img.lp-guide-thumb, img.lp-mfcard-thumb, img.lp-sheet-poster,
img.lp-sheet-still, img.lp-sheet-trailer-img {
  opacity: 0;
  transition: opacity 0.4s ease;
}
img.lp-strip-photo.is-loaded, img.lp-map-photo.is-loaded, img.lp-sheet-photo.is-loaded, img.lp-map-img.is-loaded,
img.lp-place-thumb.is-loaded, img.lp-guide-thumb.is-loaded, img.lp-mfcard-thumb.is-loaded,
img.lp-sheet-poster.is-loaded, img.lp-sheet-still.is-loaded, img.lp-sheet-trailer-img.is-loaded {
  opacity: 1;
}
@media (prefers-reduced-motion: reduce) {
  img.lp-strip-photo, img.lp-map-photo, img.lp-sheet-photo, img.lp-map-img,
  img.lp-place-thumb, img.lp-guide-thumb, img.lp-mfcard-thumb, img.lp-sheet-poster,
  img.lp-sheet-still, img.lp-sheet-trailer-img { transition: none; }
}

/* ── Canonical recipe (server-built from one page's Recipe JSON-LD) ────────── */
.lp-recipe-wrap {
  display: block; width: 100%; max-width: 800px; min-width: 0; box-sizing: border-box;
  margin: 0; color: var(--text-primary); font-family: var(--font-system);
}
.lp-recipe-head { padding: 0 2px 13px; border-bottom: 1px solid var(--wv-hairline); }
.lp-recipe-title { margin: 0; font-size: 1.08rem; line-height: 1.3; font-weight: 760; letter-spacing: -0.01em; }
.lp-recipe-metrics {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(92px, 1fr));
  gap: 8px 16px; margin-top: 11px;
}
.lp-recipe-metric { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.lp-recipe-key { color: var(--text-tertiary); font-size: 0.7rem; line-height: 1.2; text-transform: uppercase; letter-spacing: 0.045em; font-weight: 650; }
.lp-recipe-value { color: var(--text-primary); font-size: 0.86rem; line-height: 1.35; font-weight: 650; font-variant-numeric: tabular-nums; }
.lp-recipe-source {
  display: flex; align-items: center; flex-wrap: wrap; gap: 3px; max-width: 100%; margin-top: 9px;
  color: var(--text-secondary); font-size: 0.74rem; line-height: 1.35; font-weight: 550;
  overflow-wrap: anywhere;
}
.lp-recipe-source > a:not(.lp-recipe-cite) { color: inherit; font-weight: inherit; text-decoration: underline; text-underline-offset: 2px; }
.lp-recipe-cite {
  display: inline-grid !important; place-items: center; min-width: 15px; height: 15px; padding: 0 3px;
  margin-left: 4px; box-sizing: border-box; border-radius: 999px; text-decoration: none !important;
  background: var(--wv-chip-tint); color: var(--text-secondary) !important;
  font-size: 9px; line-height: 1; font-weight: 700 !important; vertical-align: 1px; white-space: nowrap;
}
.lp-recipe-section { margin-top: 18px; }
.lp-recipe-section h3 { margin: 0 0 8px; font-size: 1rem; line-height: 1.35; font-weight: 740; }
.lp-recipe-ingredients, .lp-recipe-steps { list-style: none; margin: 0; padding: 0; }
.lp-recipe-ingredients { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 28px; }
.lp-recipe-ingredients li {
  position: relative; min-width: 0; padding: 7px 0 7px 14px; border-top: 1px solid var(--wv-hairline);
  font-size: 0.9rem; line-height: 1.42; overflow-wrap: anywhere;
}
.lp-recipe-ingredients li::before { content: ""; position: absolute; left: 2px; top: 14px; width: 4px; height: 4px; border-radius: 50%; background: var(--text-secondary); }
.lp-recipe-steps { counter-reset: recipe-step; }
.lp-recipe-steps li {
  counter-increment: recipe-step; position: relative; min-width: 0; padding: 10px 0 10px 34px;
  border-top: 1px solid var(--wv-hairline); font-size: 0.9rem; line-height: 1.48; overflow-wrap: anywhere;
}
.lp-recipe-steps li::before {
  content: counter(recipe-step) "."; position: absolute; left: 2px; top: 10px;
  width: 24px; color: var(--text-secondary); font-weight: 700; font-variant-numeric: tabular-nums;
}
.lp-recipe-ingredients li:first-child, .lp-recipe-steps li:first-child { border-top: 0; padding-top: 0; }
.lp-recipe-ingredients li:first-child::before { top: 7px; }
.lp-recipe-steps li:first-child::before { top: 0; }
.lp-recipe-wrap strong { font-weight: 720; color: var(--text-primary); }
@media (max-width: 560px) {
  .lp-recipe-metrics { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px 10px; }
  .lp-recipe-ingredients { grid-template-columns: 1fr; }
  .lp-recipe-section { margin-top: 15px; }
  .lp-recipe-ingredients li { padding-top: 6px; padding-bottom: 6px; }
  .lp-recipe-steps li { padding-top: 9px; padding-bottom: 9px; }
}

/* ── Domestic weekend box office (server-built `box_office` block) ─────────── */
.lp-box-office-wrap {
  display: block; width: 100%; max-width: 620px; min-width: 0; box-sizing: border-box;
  margin: 2px 0 4px; color: var(--text-primary); font-family: var(--font-system);
}
.lp-bo-head { padding: 0 2px 10px; border-bottom: 1px solid var(--wv-hairline); }
.lp-bo-heading { font-size: 1rem; line-height: 1.3; font-weight: 750; letter-spacing: -0.01em; }
.lp-bo-scope { margin-top: 3px; font-size: 0.8rem; line-height: 1.4; color: var(--text-secondary); }
.lp-bo-status { color: var(--text-primary); font-weight: 700; }
.lp-bo-list { display: flex; flex-direction: column; }
.lp-bo-row {
  display: grid; grid-template-columns: 36px minmax(0, 1fr) auto; column-gap: 10px;
  align-items: start; min-width: 0; padding: 11px 2px; border-top: 1px solid var(--wv-hairline);
}
.lp-bo-row:first-child { border-top: 0; }
.lp-bo-rank { padding-top: 2px; font-size: 0.82rem; line-height: 1.35; font-weight: 750; color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.lp-bo-main { min-width: 0; }
.lp-bo-title { font-size: 0.98rem; line-height: 1.28; font-weight: 700; color: var(--text-primary); }
.lp-bo-meta { margin-top: 3px; font-size: 0.78rem; line-height: 1.4; color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.lp-bo-gross {
  display: flex; align-items: flex-start; gap: 3px; padding-top: 0;
  color: var(--text-primary); font-size: 1.08rem; line-height: 1.3; font-weight: 780;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.lp-bo-cites { display: inline-flex; gap: 2px; padding-top: 1px; }
.lp-bo-cite {
  display: inline-grid; place-items: center; min-width: 15px; height: 15px; padding: 0 3px;
  box-sizing: border-box; border-radius: 999px; text-decoration: none;
  background: var(--wv-chip-tint); color: var(--text-secondary); font-size: 9px; line-height: 1; font-weight: 700;
}
.lp-bo-cite:hover, .lp-bo-cite:focus-visible { background: color-mix(in srgb, var(--wv-accent) 14%, transparent); color: var(--wv-accent); }
@media (max-width: 480px) {
  .lp-bo-row { grid-template-columns: 28px minmax(0, 1fr) auto; column-gap: 8px; padding: 10px 1px; }
  .lp-bo-title { font-size: 0.93rem; }
  .lp-bo-gross { font-size: 1rem; }
  .lp-bo-meta { font-size: 0.74rem; }
}

/* ── Movie card list + detail sheet (server-built `movies` block: now playing) ── */
.lp-movies-wrap { display: block; margin: 2px 0 6px; max-width: 620px; }
.lp-movie-section { font-weight: 700; font-size: 1rem; margin: 14px 0 4px; color: var(--text-primary); }
.lp-movie-list { display: flex; flex-direction: column; }
.lp-movie {
  display: flex; gap: 12px; align-items: flex-start; padding: 9px 4px; cursor: pointer;
  border-top: 1px solid var(--divider, #e6e3db); text-align: left; border-radius: 8px;
}
.lp-movie:first-child { border-top: none; }
.lp-movie:hover { background: color-mix(in srgb, var(--text-primary) 3%, transparent); }
.lp-movie-poster {
  flex: none; width: 58px; aspect-ratio: 2 / 3; border-radius: 8px; object-fit: cover;
  background: var(--divider, #e6e3db);
}
.lp-movie-poster-none {
  display: inline-flex; width: 48px; aspect-ratio: 1 / 1; align-self: center;
  align-items: center; justify-content: center; font-size: 20px;
  color: var(--text-secondary); opacity: 1;
}
.lp-movie-body { flex: 1 1 auto; min-width: 0; }
.lp-movie-name { font-weight: 700; font-size: 1.02rem; line-height: 1.25; color: var(--text-primary); }
.lp-movie-name .lp-movie-year { font-weight: 500; color: var(--text-secondary); }
.lp-movie-rates { display: flex; flex-wrap: wrap; gap: 6px; margin: 5px 0 2px; }
.lp-movie-rate {
  display: inline-flex; align-items: center; gap: 3px; font-size: 0.8rem; line-height: 1.5;
  padding: 1px 8px; border-radius: 999px;
  background: color-mix(in srgb, var(--text-primary) 7%, transparent); color: var(--text-primary);
}
.lp-movie-imdb b { color: #c99700; }
.lp-movie-mc b { color: #4a9d5b; }
.lp-movie-meta { font-size: 0.82rem; color: var(--text-secondary); margin-top: 2px; }
.lp-movie-desc { font-size: 0.9rem; line-height: 1.42; color: var(--text-primary); margin-top: 4px; }
.lp-movie-venues { font-size: 0.85rem; line-height: 1.42; color: var(--text-secondary); margin-top: 3px; }
.lp-movie-chev { flex: none; align-self: center; color: var(--text-secondary); font-size: 1.3rem; line-height: 1; }

.lp-sheet-poster-wrap { display: block; text-align: center; margin-bottom: 12px; }
.lp-sheet-poster { max-height: 300px; max-width: 200px; width: auto; border-radius: 12px; object-fit: cover; }
/* Trailer + stills media strip (TMDB) at the top of the movie detail sheet. */
.lp-sheet-media {
  display: flex; gap: 8px; overflow-x: auto; margin: 0 0 14px; padding-bottom: 4px;
  -webkit-overflow-scrolling: touch; scrollbar-width: none;
}
.lp-sheet-media::-webkit-scrollbar { display: none; }
.lp-sheet-still, .lp-sheet-trailer-img {
  height: 132px; aspect-ratio: 16 / 9; flex: none; border-radius: 10px; object-fit: cover;
  background: var(--divider, #e6e3db); display: block;
}
.lp-sheet-still { cursor: zoom-in; }
.lp-sheet-media-item { position: relative; flex: none; display: block; line-height: 0; border-radius: 10px; overflow: hidden; cursor: pointer; }
.lp-sheet-play {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: 42px; height: 42px; border-radius: 50%; background: rgba(0, 0, 0, 0.62); color: #fff;
  display: flex; align-items: center; justify-content: center; font-size: 15px; padding-left: 3px;
}
.lp-sheet-trailer-label {
  position: absolute; bottom: 6px; left: 6px; color: #fff; font-size: 0.68rem; font-weight: 600;
  background: rgba(0, 0, 0, 0.55); padding: 1px 8px; border-radius: 999px; line-height: 1.6;
}
.lp-sheet-rates {
  display: flex; margin: 10px 0 14px; border-radius: 12px; overflow: hidden;
  border: 1px solid var(--divider, #e6e3db);
}
.lp-sheet-rate {
  flex: 1 1 0; display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 10px 6px; text-decoration: none; color: var(--text-primary);
  border-left: 1px solid var(--divider, #e6e3db);
}
.lp-sheet-rate:first-child { border-left: none; }
.lp-sheet-rate:hover { background: color-mix(in srgb, var(--text-primary) 4%, transparent); }
.lp-sheet-rate b { font-size: 1.05rem; }
.lp-sheet-rate span { font-size: 0.75rem; color: var(--text-secondary); }
.lp-place-list { display: flex; flex-direction: column; }
.lp-place {
  display: flex; align-items: center; gap: 10px; width: 100%; padding: 10px 12px;
  box-sizing: border-box;   /* width:100% + padding must not overflow the card (mobile row cut-off) */
  min-width: 0;
  background: none; border: none; border-top: 1px solid color-mix(in srgb, var(--border-color) 70%, transparent);
  text-align: left; cursor: pointer; font: inherit; color: var(--text-primary); -webkit-tap-highlight-color: transparent;
}
.lp-place:first-child { border-top: none; }
.lp-place:active { background: color-mix(in srgb, var(--text-primary) 6%, transparent); }
.lp-place-num { flex: none; width: 20px; height: 20px; border-radius: 999px; background: var(--wv-accent); color: #fff; font-size: 12px; font-weight: 700; display: grid; place-items: center; }
.lp-place-thumb { flex: none; width: 44px; height: 44px; border-radius: 10px; object-fit: cover; background: color-mix(in srgb, var(--text-primary) 8%, transparent); }
.lp-place-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.lp-place-name { font-weight: 700; font-size: 14.5px; min-width: 0; }
.lp-place-name-row { display: flex; align-items: center; gap: 6px; min-width: 0; }
.lp-place-meta { font-size: 0.8rem; color: var(--text-secondary); }
.lp-place-addr { font-size: 0.78rem; color: var(--text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lp-place-chev { flex: none; color: var(--text-secondary); font-size: 1.3rem; opacity: 0.45; }

/* ── Place bottom sheet (tap a place → slide up; drag/tap-out to dismiss) ──
   Main text = ink/black; dark-blue (--wv-accent) is a HIGHLIGHT only (buttons, status). */
/* Scroll-lock is MOBILE-ONLY: on desktop, killing the page scrollbar reflows/recenters the
   560px column by a fractional offset and every glyph re-rasterizes visibly "bolder" while the
   panel is open. The desktop right-panel keeps the page live behind it (Google-style) anyway. */
@media (max-width: 699.98px) { body.lp-sheet-open { overflow: hidden; } }
.lp-sheet-wrap { position: fixed; inset: 0; z-index: 60; display: flex; align-items: flex-end; justify-content: center; }
.lp-sheet-wrap[hidden] { display: none; }   /* else display:flex overrides [hidden] and the closed wrap keeps eating clicks */
.lp-sheet-wrap:not(.open) { pointer-events: none; }   /* let clicks pass through during the slide-down close */
.lp-sheet-backdrop { position: absolute; inset: 0; background: rgba(0, 0, 0, 0.35); opacity: 0; transition: opacity 0.28s ease; }
.lp-sheet-wrap.open .lp-sheet-backdrop { opacity: 1; }
.lp-sheet {
  position: relative; width: 100%; max-width: 740px; max-height: 78vh;   /* input-bar width, centered — not full screen */
  color: var(--text-primary);                                            /* base = ink (never inherit a tint) */
  background: var(--bg-app); border-radius: 20px 20px 0 0; box-shadow: 0 -8px 40px rgba(0, 0, 0, 0.25);
  transform: translateY(100%); transition: transform 0.34s cubic-bezier(0.22, 1, 0.32, 1);
  display: flex; flex-direction: column; padding-bottom: env(safe-area-inset-bottom);
}
.lp-sheet-wrap.open .lp-sheet { transform: translateY(0); }
.lp-sheet-grip { flex: none; height: 26px; cursor: grab; position: relative; touch-action: none; }
.lp-sheet-grip:active { cursor: grabbing; }
.lp-sheet-grip::before { content: ""; position: absolute; top: 9px; left: 50%; transform: translateX(-50%); width: 40px; height: 4px; border-radius: 999px; background: color-mix(in srgb, var(--text-primary) 24%, transparent); }
.lp-sheet-x { position: absolute; top: 10px; right: 12px; width: 30px; height: 30px; border: none; border-radius: 999px; background: color-mix(in srgb, var(--text-primary) 8%, transparent); color: var(--text-primary); font-size: 14px; cursor: pointer; z-index: 2; }
.lp-sheet-body { overflow-y: auto; -webkit-overflow-scrolling: touch; overscroll-behavior: contain; touch-action: pan-y; padding: 2px 18px 24px; }
/* While the sheet is being dragged: no text selection, grabbing cursor everywhere. */
.lp-sheet-dragging, .lp-sheet-dragging * { user-select: none !important; cursor: grabbing !important; }
.lp-sheet-loading { padding: 44px 0; text-align: center; color: var(--text-secondary); }
/* ── Place detail card (ChatGPT-style): big name, filled Directions pill, icon info rows ── */
.lp-sheet-name { font-family: var(--font-system); font-size: 1.5rem; font-weight: 700; line-height: 1.15; padding-right: 34px; color: var(--text-primary); }
.lp-sheet-meta { font-size: 0.95rem; color: var(--text-secondary); margin-top: 5px; }
.lp-sheet-rating { color: var(--text-primary); font-weight: 600; }
.lp-sheet-photos { display: flex; gap: 8px; overflow-x: auto; margin: 4px 0 14px; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
.lp-sheet-photos::-webkit-scrollbar { display: none; }
.lp-sheet-photo { height: 172px; aspect-ratio: 3 / 2; border-radius: 14px; flex: none; cursor: zoom-in; object-fit: cover; }
.lp-sheet-actions { display: flex; gap: 10px; margin: 14px 0 6px; }
.lp-sheet-act {
  flex: 1 1 0; min-width: 0; box-sizing: border-box; display: inline-flex; align-items: center; justify-content: center;
  padding: 12px 10px; border-radius: 999px; border: 1.5px solid var(--border-color);
  background: transparent; color: var(--text-primary);
  font-size: 0.94rem; font-weight: 600; text-decoration: none; white-space: nowrap; overflow: hidden;
  -webkit-tap-highlight-color: transparent;
}
.lp-sheet-act:active { background: color-mix(in srgb, var(--text-primary) 8%, transparent); }
.lp-sheet-act-primary { background: var(--text-primary); color: var(--bg-app); border-color: var(--text-primary); }
.lp-sheet-act-primary:active { background: color-mix(in srgb, var(--text-primary) 84%, transparent); }
/* Icon info rows (hours / address / phone) with thin dividers, ChatGPT-style */
.lp-sheet-row { display: flex; align-items: flex-start; gap: 12px; padding: 14px 2px; border-top: 1px solid var(--divider); }
.lp-sheet-rowbtn { display: flex; align-items: flex-start; gap: 12px; width: 100%; background: none; border: none; padding: 0; margin: 0; font: inherit; text-align: left; cursor: pointer; color: inherit; }
.lp-sheet-ic { flex: none; color: var(--text-tertiary); margin-top: 1px; }
.lp-sheet-row-main { flex: 1; min-width: 0; font-size: 0.98rem; line-height: 1.35; color: var(--text-primary); }
.lp-sheet-phone { color: var(--wv-accent); text-decoration: none; }
/* Collapsible hours: a summary line ("Open · Closes 10 PM") that expands to the full week. */
.lp-sheet-row.lp-hours { flex-direction: column; align-items: stretch; }
.lp-hr-open { color: var(--wv-up, #12a150); font-weight: 600; }
.lp-hr-closed { color: var(--wv-down, #d1483a); font-weight: 600; }
.lp-hours-chev { flex: none; color: var(--text-tertiary); transition: transform 0.2s ease; margin-top: 1px; }
.lp-hours.expanded .lp-hours-chev { transform: rotate(180deg); }
.lp-hours-full { display: none; margin-top: 10px; padding-left: 31px; }
.lp-hours.expanded .lp-hours-full { display: block; }
/* Hours rows: DAY name semibold, times regular; only TODAY's whole row is bold. */
.lp-sheet-hr { font-size: 0.9rem; font-weight: 400; padding: 3px 0; color: var(--text-primary); }
.lp-hr-day { font-weight: 600; }
.lp-hr-today, .lp-hr-today .lp-hr-day { font-weight: 700; }
.lp-sheet-summary { font-size: 0.98rem; line-height: 1.5; margin: 14px 0 4px; padding-top: 14px; border-top: 1px solid var(--divider); color: var(--text-primary); }
.lp-sheet-sec { border-top: 1px solid var(--divider); padding-top: 14px; margin-top: 14px; }
.lp-sheet-sec-h { font-weight: 700; font-size: 1.05rem; color: var(--text-primary); margin-bottom: 10px; }
.lp-sheet-rev { padding: 8px 0; }
.lp-sheet-rev-top { font-size: 0.85rem; font-weight: 400; color: var(--text-secondary); }
.lp-sheet-rev-txt { font-size: 0.94rem; font-weight: 400; line-height: 1.45; margin-top: 2px; color: var(--text-primary); }

/* Link preview (tap a source card → side panel / sheet with the article + an Open action) */
.lp-sheet-link-img { width: 100%; max-height: 230px; object-fit: cover; border-radius: 14px; margin: 4px 0 14px; background: var(--divider); }
.lp-sheet-link-meta { display: flex; align-items: center; gap: 7px; }
.lp-sheet-link-meta .lp-source-fav { width: 16px; height: 16px; border-radius: 4px; }
/* …and it is a fixed-fit card — NO scrolling. Over-long titles/snippets end in an ellipsis;
   the image flexes down to absorb short viewports so the Open action is never pushed out of
   view. (`.lp-sheet-link` on the sheet is set by openSheet(html, 'link'); place/movie sheets
   keep their normal scrolling detail content.) */
.lp-sheet-link .lp-sheet-body { overflow-y: hidden; display: flex; flex-direction: column; }
.lp-sheet-link .lp-sheet-head, .lp-sheet-link .lp-sheet-summary, .lp-sheet-link .lp-sheet-actions { flex: none; }
.lp-sheet-link .lp-sheet-link-img { flex: 0 1 auto; min-height: 0; }
.lp-sheet-link .lp-sheet-name { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden; }
.lp-sheet-link .lp-sheet-summary { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 5; overflow: hidden; }

/* Desktop: the place card FLOATS as a right-side panel over the map (mobile keeps the bottom sheet). */
@media (min-width: 700px) {
  .lp-sheet-wrap { align-items: stretch; justify-content: flex-end; pointer-events: none; }   /* map stays interactive; only the panel catches clicks (close via ✕ / edge-drag / outside click) */
  .lp-sheet-backdrop { background: transparent; }
  .lp-sheet {
    pointer-events: auto; width: 360px; max-width: 40vw; height: 100%; max-height: 100%;
    border-radius: 22px 0 0 22px; box-shadow: -10px 0 44px rgba(0,0,0,0.22);
    transform: translateX(100%); transition: transform 0.32s cubic-bezier(0.22,1,0.32,1);
    padding-bottom: 0;
  }
  .lp-sheet-wrap.open .lp-sheet { transform: translateX(0); }
  /* Vertical grip on the panel's left edge — drag RIGHT to dismiss (mirrors the mobile top
     grip). Sits inside the body's 18px left padding, so it never overlaps content. */
  .lp-sheet-grip { position: absolute; left: 0; top: 0; bottom: 0; width: 14px; height: auto; }
  .lp-sheet-grip::before { top: 50%; left: 5px; transform: translateY(-50%); width: 4px; height: 44px; }
  .lp-sheet-body { padding-top: 16px; }
}

/* Live map embedded in the place sheet (Maps JS SDK). Collapsed until it hydrates, so a
   missing key / SDK failure leaves no empty box. */
.lp-sheet-map { height: 0; border-radius: 14px; overflow: hidden; margin: 4px 0 14px; background: var(--wv-chip-tint); transition: height 0.2s ease; }
.lp-sheet-map.lp-sheet-map-on { height: 190px; }
.lp-sheet-map.lp-sheet-map-off { height: 0; margin: 0; }
.lp-sheet-map-canvas { width: 100%; height: 100%; }

/* Structured "mono card" bubbles (box-drawing panels, tables, charts, sparklines):
   monospace + preserved whitespace so columns stay aligned; scrolls if too wide. */
.lp-bubble.lp-mono {
  max-width: 94%;
  font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11.5px; line-height: 1.35; letter-spacing: 0;
  white-space: pre; overflow-x: auto; -webkit-overflow-scrolling: touch;
  padding: 10px 12px; tab-size: 2;
}
.lp-bubble.lp-mono::-webkit-scrollbar { height: 6px; }
.lp-bubble.lp-mono::-webkit-scrollbar-thumb { background: rgba(128,128,128,.32); border-radius: 4px; }
/* Wrapping mono card (news/feed): monospace + box-drawing rules, but long headlines wrap. */
.lp-bubble.lp-mono.lp-wrap { white-space: pre-wrap; overflow-x: visible; word-break: break-word; font-size: 12.5px; line-height: 1.42; }
.lp-bubble.lp-mono.lp-wrap b { font-weight: 700; }

/* iMessage tails removed for now — plain rounded bubbles. */
.lp-row .lp-bubble::before, .lp-row .lp-bubble::after { display: none !important; }

/* ── Typing dots — a tailless bubble ringed by a Border Beam ───────────────
   Same border-beam port as the composer, ocean — tuned toward a crisp LINE
   rather than a glow: a fast (1.2s lap), 1.5px ring, short bright streak.
   No inner-glow wash; the bloom is a tight 2.5px streak, not a halo. Layers: ::after = border stroke, .lp-beam-bloom child = hot core.
   The width ease below lets the pill morph between dots and status labels
   while the beam ring rides straight through. */
.lp-typing-wrap {
  --lp-beam-hue: 30deg; --lp-beam-sat: 2.2;
  --lp-beam-stroke-op: 0.5; --lp-beam-bloom-op: 0.5;
  position: relative; display: inline-block; border-radius: var(--imsg-bubble-radius);
  isolation: isolate; padding: 2px; overflow: hidden;
  animation: lp-beam-spin 1.2s linear infinite, lp-beam-fade-in 0.6s ease both;
}
[data-theme="dark"] .lp-typing-wrap {
  --lp-beam-sat: 1.5;
  --lp-beam-stroke-op: 0.6; --lp-beam-bloom-op: 0.45;
}
/* Border stroke — ocean blobs + a sheen, masked to a hairline 0.5px ring and a rotating window. */
.lp-typing-wrap::after {
  content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none;
  border-radius: calc(var(--imsg-bubble-radius) - 1.5px); padding: 1.5px;
  clip-path: inset(0 round var(--imsg-bubble-radius));
  background:
    conic-gradient(from var(--lp-beam-angle),
      transparent 0%, transparent 54%,
      rgba(0, 0, 0, 0.08) 57%, rgba(0, 0, 0, 0.2) 60%, rgba(0, 0, 0, 0.4) 63%,
      rgba(0, 0, 0, 0.55) 66%, rgba(0, 0, 0, 0.4) 69%, rgba(0, 0, 0, 0.2) 72%,
      rgba(0, 0, 0, 0.08) 75%, transparent 78%, transparent 100%),
    radial-gradient(ellipse 9px 18px at 2% 68%, rgb(60, 140, 200), transparent),
    radial-gradient(ellipse 4px 8px at 2% 68%, rgb(50, 120, 180), transparent),
    radial-gradient(ellipse 59px 9px at 72% -3%, rgb(100, 80, 220), transparent),
    radial-gradient(ellipse 42px 7px at 74% 100%, rgb(80, 100, 255), transparent),
    radial-gradient(ellipse 10px 17px at 100% 27%, rgb(120, 70, 240), transparent),
    radial-gradient(ellipse 10px 18px at 100% 27%, rgb(90, 80, 220), transparent),
    radial-gradient(ellipse 5px 10px at 100% 27%, rgb(70, 110, 255), transparent),
    radial-gradient(ellipse 11px 12px at 100% 27%, rgb(110, 90, 230), transparent);
  -webkit-mask:
    conic-gradient(from var(--lp-beam-angle),
      transparent 0%, transparent 44%,
      rgba(255, 255, 255, 0.1) 50%, rgba(255, 255, 255, 0.35) 57%,
      white 62%, white 74%,
      rgba(255, 255, 255, 0.35) 79%, rgba(255, 255, 255, 0.1) 84%,
      transparent 88%, transparent 100%),
    linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: source-in, xor;
  mask:
    conic-gradient(from var(--lp-beam-angle),
      transparent 0%, transparent 44%,
      rgba(255, 255, 255, 0.1) 50%, rgba(255, 255, 255, 0.35) 57%,
      white 62%, white 74%,
      rgba(255, 255, 255, 0.35) 79%, rgba(255, 255, 255, 0.1) 84%,
      transparent 88%, transparent 100%),
    linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  mask-composite: intersect, exclude;
  opacity: calc(var(--lp-beam-opacity) * var(--lp-beam-stroke-op));
  animation: lp-beam-hue 12s ease-in-out infinite;
}
[data-theme="dark"] .lp-typing-wrap::after {
  background:
    conic-gradient(from var(--lp-beam-angle),
      transparent 0%, transparent 54%,
      rgba(255, 255, 255, 0.1) 57%, rgba(255, 255, 255, 0.3) 60%, rgba(255, 255, 255, 0.6) 63%,
      rgba(255, 255, 255, 0.75) 66%, rgba(255, 255, 255, 0.6) 69%, rgba(255, 255, 255, 0.3) 72%,
      rgba(255, 255, 255, 0.1) 75%, transparent 78%, transparent 100%),
    radial-gradient(ellipse 9px 18px at 2% 68%, rgb(60, 140, 200), transparent),
    radial-gradient(ellipse 4px 8px at 2% 68%, rgb(50, 120, 180), transparent),
    radial-gradient(ellipse 59px 9px at 72% -3%, rgb(100, 80, 220), transparent),
    radial-gradient(ellipse 42px 7px at 74% 100%, rgb(80, 100, 255), transparent),
    radial-gradient(ellipse 10px 17px at 100% 27%, rgb(120, 70, 240), transparent),
    radial-gradient(ellipse 10px 18px at 100% 27%, rgb(90, 80, 220), transparent),
    radial-gradient(ellipse 5px 10px at 100% 27%, rgb(70, 110, 255), transparent),
    radial-gradient(ellipse 11px 12px at 100% 27%, rgb(110, 90, 230), transparent);
}
/* Bloom — the hot core at the beam head, tightened to a crisp streak (no halo). */
.lp-typing-wrap .lp-beam-bloom {
  position: absolute; inset: 0; z-index: 3; pointer-events: none;
  border-radius: calc(var(--imsg-bubble-radius) - 1.5px); padding: 1.5px;
  clip-path: inset(0 round var(--imsg-bubble-radius));
  background: conic-gradient(from var(--lp-beam-angle),
    transparent 0%, transparent 62%,
    rgba(0, 0, 0, 0.02) 65%, rgba(0, 0, 0, 0.08) 67%, rgba(0, 0, 0, 0.2) 68.5%,
    rgba(0, 0, 0, 0.4) 69.5%, rgba(0, 0, 0, 0.6) 70.5%, rgba(0, 0, 0, 0.6) 71%,
    rgba(0, 0, 0, 0.4) 72%, rgba(0, 0, 0, 0.2) 73.5%, rgba(0, 0, 0, 0.08) 75%,
    rgba(0, 0, 0, 0.02) 77%, transparent 80%);
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  mask-composite: exclude;
  filter: blur(2.5px) brightness(1.3) saturate(var(--lp-beam-sat));
  opacity: calc(var(--lp-beam-opacity) * var(--lp-beam-bloom-op));
}
[data-theme="dark"] .lp-typing-wrap .lp-beam-bloom {
  background: conic-gradient(from var(--lp-beam-angle),
    transparent 0%, transparent 62%,
    rgba(255, 255, 255, 0.03) 65%, rgba(255, 255, 255, 0.08) 67%, rgba(255, 255, 255, 0.2) 68.5%,
    rgba(255, 255, 255, 0.45) 69.5%, rgba(255, 255, 255, 0.85) 70.5%, rgba(255, 255, 255, 0.85) 71%,
    rgba(255, 255, 255, 0.45) 72%, rgba(255, 255, 255, 0.2) 73.5%, rgba(255, 255, 255, 0.08) 75%,
    rgba(255, 255, 255, 0.03) 77%, transparent 80%);
}
.lp-typing {
  display: inline-flex; align-items: center; justify-content: flex-start; gap: 8px; overflow: hidden;
  background: var(--imsg-bubble-grey); border-radius: var(--imsg-bubble-radius);
  height: 31px; box-sizing: border-box; padding: 0 14px; position: relative;
  animation: chat-fade-in 0.2s ease-out both;
  width: auto; transition: width 0.26s cubic-bezier(0.22, 0.61, 0.36, 1);
}
/* Dots and label share ONE status slot so the favicon strip can sit on the same row.
   The pill's width eases from one label to the next while the beam ring keeps its shape. */
.lp-status-slot { display: inline-grid; place-items: center start; flex: 0 0 auto; min-width: 0; }
.lp-status-dots, .lp-status-text { grid-area: 1 / 1; }
.lp-status-text { opacity: 0; transition: opacity 0.18s ease; font-size: 0.95rem; color: var(--imsg-bubble-grey-text); white-space: nowrap; }
.lp-status-dots { display: inline-flex; gap: 5px; align-items: center; transition: opacity 0.18s ease; }
.lp-typing.has-label .lp-status-dots { opacity: 0; }
.lp-status-dots span {
  display: inline-block; width: 7px; height: 7px; border-radius: 999px;
  background: #98998c; opacity: 0.6; animation: lp-typing-pulse 1.2s ease-in-out infinite;
}
[data-theme="dark"] .lp-status-dots span { background: #8e9aa8; }
.lp-status-dots span:nth-child(2) { animation-delay: 0.15s; }
.lp-status-dots span:nth-child(3) { animation-delay: 0.30s; }
@keyframes lp-typing-pulse { 0%, 60%, 100% { opacity: 0.4; transform: translateY(0); } 30% { opacity: 1; transform: translateY(-2px); } }

/* ── Orb pill (ORB_PILL in waivy-ui.js) ──────────────────────────────────────
   The dotted 3D solving orb replaces the three dots, with a shimmer sweeping
   across the rotating caption. Everything here is scoped to .is-orb, so the
   legacy dots pill above is untouched when the flag is off. */
/* NO pill: the indicator is just the orb and the caption sitting on the page. The bubble
   background, its fixed height/padding and the border-beam ring are all dropped, and the
   width no longer needs easing (paintPillLabel skips the resize for .is-orb). */
.lp-typing-wrap.is-orb::after, .lp-typing-wrap.is-orb .lp-beam-bloom { display: none; }
.lp-typing.is-orb {
  background: none; border-radius: 0; height: auto; padding: 2px 0;
  overflow: visible; width: auto !important; gap: 8px;
}
.lp-status-orb { display: block; width: 20px; height: 20px; flex: 0 0 auto; }
/* ROLLER. .lp-status-text is the clip window — one line tall — and each caption is a
   .lp-status-line inside it. On a swap the outgoing line travels UP out of the window
   while the incoming one rises into it from below, so a word is on screen the whole time
   instead of blinking out and being replaced. 1.5em of window clears descenders (the g
   in "searching"/"working") without leaving a visible gap above the cap height. */
.lp-typing.is-orb .lp-status-text {
  opacity: 1; display: block; position: relative;
  height: 1.5em; line-height: 1.5em; overflow: hidden;
  perspective: 140px;                    /* the drum's depth — smaller curves harder */
}
.lp-typing.is-orb .lp-status-line {
  display: block; white-space: nowrap; line-height: 1.5em;
  /* Each caption is a face on a cylinder: pushing the transform origin back by the drum's
     radius (half the window) means rotating about X sweeps the line around the barrel
     rather than spinning it in place. The iOS picker-wheel construction. */
  transform-origin: center center -0.75em;
  backface-visibility: hidden;
  transition: transform 520ms cubic-bezier(0.22, 0.61, 0.36, 1);
  /* Shimmer: a band sweeps along the text via background-clip. Sampled off the
     reference clip — background #f9f6f3, glyph base grey ~100, sweeping to ~218 — so the
     band LIGHTENS the letters toward the page as it passes rather than darkening them.
     The gradient is 220% wide so the band travels the word instead of washing it at once. */
  background-image: linear-gradient(100deg,
    var(--wv-shimmer-base) 38%, var(--wv-shimmer-hi) 50%, var(--wv-shimmer-base) 62%);
  background-size: 220% 100%;
  background-repeat: no-repeat;
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
  animation: lp-orb-shimmer 2s linear infinite;
}
/* Source favicons ride the same drum, turned on its side: the current stack rotates away
   to the LEFT about Y while the next swings in from the RIGHT. Origin pushed back by
   roughly half a four-icon stack (14px + 3×9px overlap ≈ 41px) so the faces travel around
   a barrel rather than pivoting on the spot, exactly as the caption lines do. */
.lp-typing.is-orb .lp-fav-strip { position: relative; overflow: hidden; perspective: 140px; }
.lp-typing.is-orb .lp-fav-face {
  display: inline-flex; align-items: center;
  transform-origin: center center -20px;
  backface-visibility: hidden;
  transition: transform 520ms cubic-bezier(0.22, 0.61, 0.36, 1);
}
.lp-typing.is-orb .lp-fav-face.is-enter { transform: rotateY(90deg); }
.lp-typing.is-orb .lp-fav-face.is-out {
  position: absolute; left: 0; top: 0; transform: rotateY(-90deg);
}
@media (prefers-reduced-motion: reduce) { .lp-typing.is-orb .lp-fav-face { transition: none; } }
/* Parked on the underside of the drum, face-up, about to swing into view. */
.lp-typing.is-orb .lp-status-line.is-enter { transform: rotateX(-90deg); }
/* Gone over the top of the drum, face-down. Absolute so the incoming line owns the
   window's width straight away — they only overlap while the roll runs, and the outgoing
   node is dropped on transitionend. At the halfway point both sit near 45°, so a word is
   always on the barrel's front face; neither is ever edge-on at the same moment. */
.lp-typing.is-orb .lp-status-line.is-out {
  position: absolute; left: 0; top: 0; transform: rotateX(90deg);
}
/* The sweep LIGHTENS the glyphs (the reference's direction) but has a FLOOR: its
   brightest point still holds 4.5:1 on the page, so letters sheen instead of dropping
   out. The reference itself swept to ~#dadada — 1.4:1, effectively invisible mid-word.
   Amplitude is 79 grey levels — the base goes near-ink so the sweep has room to read
   clearly while its BRIGHTEST point still holds that 4.5:1 floor. Warm-tinted to sit with
   the sand/ink palette rather than neutral grey. Dark needs no floor — brightening toward
   white only adds contrast, so its base drops instead to widen the range. */
:root { --wv-shimmer-base: #2b2924; --wv-shimmer-hi: #7a766b; }
[data-theme="dark"] { --wv-shimmer-base: #79879a; --wv-shimmer-hi: #ffffff; }
/* 100% → 0%, NOT 150% → -50%. The gradient is 220% of the text box and does not repeat,
   so at |position| outside 0–100% it slides partly OFF the box — and glyphs with no
   background behind them render fully transparent (text-fill-color is transparent), which
   is what made the caption drop out mid-word. Within 0–100% the image always covers the
   box, and the highlight still travels past both edges (its band runs -0.1 → 1.1). */
@keyframes lp-orb-shimmer { from { background-position: 100% 0; } to { background-position: 0% 0; } }
@media (prefers-reduced-motion: reduce) {
  /* No sweep — the caption still has to READ, so fall back to a flat solid fill
     rather than leaving transparent text over a frozen gradient. No roll either: the
     swap is instant, and paintPillLabel's timeout (not transitionend, which never
     fires without a transition) is what drops the outgoing line. */
  .lp-typing.is-orb .lp-status-line {
    animation: none; background-image: none;
    -webkit-text-fill-color: var(--imsg-bubble-grey-text); color: var(--imsg-bubble-grey-text);
    transition: none;
  }
  .lp-typing.is-orb .lp-status-line.is-out { opacity: 0; }
}

/* ── Streamed progress console — a live step timeline that replaces the "…" pill.
   Content-aware headline + ✓/○ steps + source domains, in waivy's monospace idiom.
   Painted by direct DOM mutation from api.progress (waivy-ui.js). Accent = loader blue. */
.lp-loader { display: block; }
/* Seconds timer under the "…" pill — starts when the thinking indicator appears. */
.lp-took {
  font-size: 11px; color: var(--text-tertiary); margin: 6px 2px 0;
  font-variant-numeric: tabular-nums; animation: chat-fade-in 0.25s ease both;
}
.lp-took[hidden] { display: none; }
/* Streaming answer bubble — a calm blue glow ring pulses around it while the answer
   generates; the glow is dropped on completion (parity with the old glowing loader bubble). */
.lp-bubble.lp-glow { isolation: isolate; }
.lp-bubble.lp-glow::before {
  content: ""; position: absolute; inset: -2px; z-index: -1;
  border-radius: calc(var(--imsg-bubble-radius) + 2px);
  background: conic-gradient(from 180deg,
    #6ea2f0 0deg, #4079e0 12deg, #2f5fc4 26deg, #274fa8 44deg,
    rgba(39, 79, 168, 0) 84deg, rgba(39, 79, 168, 0) 360deg);
  opacity: 0; animation: lp-glow-pulse 1.6s ease-in-out infinite; pointer-events: none;
}
@keyframes lp-glow-pulse { 0%, 100% { opacity: 0.45; } 50% { opacity: 1; } }

@keyframes chat-fade-in { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }
/* The SEND entrance: the question (every user bubble is a sent query) and the "..." dots start
   LOWER and rise UP into place — the fade completes EARLY (by 35%) so the upward glide is
   visible for most of the 0.5s instead of popping in mid-fade (the submit "jitter"). */
@keyframes lp-rise-in { 0% { opacity: 0; transform: translateY(var(--rise-from, 30px)); } 35% { opacity: 1; } 100% { opacity: 1; transform: translateY(0); } }
.lp-row.user .lp-bubble,
.lp-typing { animation: lp-rise-in 0.5s cubic-bezier(0.16, 1, 0.3, 1) both; }
@keyframes chat-pop-in { from { opacity: 0; transform: scale(0.6); } 60% { opacity: 1; transform: scale(1.06); } to { opacity: 1; transform: scale(1); } }

/* ── Composer dock — always visible, floats over the thread ──────────────── */
.lp-dock {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 10;
  padding: 4px 14px calc(8px + env(safe-area-inset-bottom)); pointer-events: none;
  /* The keyboard-occlusion correction below lands LATE (iOS fires visualViewport at the end
     of the keyboard animation) — a short transition turns the snap into a 180ms glide. */
  transition: transform 0.18s ease-out;
  /* --kb-lift: JS keyboard-occlusion correction (applyViewport) — stays 0 whenever
     Safari's native focus-scroll ride worked; lifts the dock only when it would
     otherwise sit behind the keyboard (iOS ignores interactive-widget=resizes-content). */
  transform: translateY(var(--kb-lift, 0px));
}
body.state-anim .lp-dock { transition: transform 0.45s cubic-bezier(0.22, 1, 0.36, 1); }
body.kb-room .lp-scroll { padding-bottom: calc(var(--dock-clearance) + 48vh); }
.lp-dock > * { pointer-events: auto; }
.lp-dock::before {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; top: -48px;
  background: linear-gradient(to bottom, transparent, var(--bg-app) 44%);
  z-index: -1; pointer-events: none; transition: opacity 0.3s ease;
}
.lp-dock-inner { width: 100%; max-width: var(--wv-chat-column); margin: 0 auto; box-sizing: border-box; display: flex; flex-direction: column; gap: 14px; transition: gap 0.35s ease; }
body[data-state="chat"] .lp-dock-inner { gap: 0; }
body[data-state="empty"] .lp-dock { transform: translateY(calc(-0.5 * var(--app-h, 100dvh) + 50% + 40px + var(--kb-lift, 0px))); }
body[data-state="empty"] .lp-dock::before { opacity: 0; }

/* Greeting + suggestion chips (empty state) */
.lp-hero { text-align: center; overflow: hidden; max-height: 120px; transition: opacity 0.25s ease, max-height 0.35s ease, margin 0.35s ease; }
.lp-hero h1 { font-family: var(--font-system); font-size: clamp(24px, 6vw, 34px); font-weight: 600; line-height: 1.15; letter-spacing: -0.01em; color: var(--text-primary); margin: 0 0 6px; }
.lp-dock-chips { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; overflow: hidden; max-height: 120px; transition: opacity 0.25s ease, max-height 0.35s ease, margin 0.35s ease; }
.lp-chip {
  font-family: var(--font-system); font-size: 0.86rem; color: var(--text-secondary);
  background: color-mix(in srgb, var(--bg-app) 62%, #fff); border: 1px solid var(--border-color);
  border-radius: 999px; padding: 7px 14px; cursor: pointer; white-space: nowrap;
}
.lp-chip.filled { background: var(--color-ink); color: var(--color-sand); border-color: transparent; }
/* Rotating "trending" chip: a 📈 arrow + a topic that cross-fades to the next. */
.lp-chip-trending { display: inline-flex; align-items: center; gap: 7px; transition: opacity 0.2s ease; }
.lp-chip-trending.lp-chip-swap { opacity: 0; }
.lp-trend-ic { color: #0a7cff; flex: none; }
.lp-chip-label { white-space: nowrap; }
body[data-state="chat"] .lp-hero, body[data-state="chat"] .lp-dock-chips { opacity: 0; max-height: 0; margin: 0; pointer-events: none; }

/* ── Live composer — Google-AI-Mode focus expansion + a Border Beam ring ─────
   The beam is a vanilla-CSS port of border-beam (beam.jakubantalik.com, MIT),
   color "ocean" at 100% strength. TWO states: at rest the ring is size "md"
   (Large) — a bright head laps the whole border over static ocean blobs; while
   the user is inside the input (:focus-within) it swaps to size "line" — a
   light blob traveling the bottom edge. Three layers paint each: ::after =
   border stroke, ::before = inner glow, .lp-beam-bloom = blurred hot core.
   Light theme by default; [data-theme="dark"] swaps in the dark palettes.
   The typing pill below uses the same port at size "sm". */
@property --lp-beam-angle   { syntax: '<angle>';  inherits: true; initial-value: 0deg; }
@property --lp-beam-opacity { syntax: '<number>'; inherits: true; initial-value: 0; }

@keyframes lp-beam-fade-in { to { --lp-beam-opacity: 1; } }
@keyframes lp-beam-spin { to { --lp-beam-angle: 360deg; } }
@keyframes lp-beam-hue {
  0%   { filter: hue-rotate(calc(0deg - var(--lp-beam-hue))) brightness(1.3) saturate(var(--lp-beam-sat)); }
  50%  { filter: hue-rotate(var(--lp-beam-hue)) brightness(1.3) saturate(var(--lp-beam-sat)); }
  100% { filter: hue-rotate(calc(0deg - var(--lp-beam-hue))) brightness(1.3) saturate(var(--lp-beam-sat)); }
}
/* Focus state = size "line": the beam travels the bottom edge on these oscillators. */
@property --lp-beam-x       { syntax: '<number>'; inherits: true; initial-value: 0; }
@property --lp-beam-w       { syntax: '<number>'; inherits: true; initial-value: 1; }
@property --lp-beam-h       { syntax: '<number>'; inherits: true; initial-value: 1; }
@property --lp-beam-spike   { syntax: '<number>'; inherits: true; initial-value: 1; }
@property --lp-beam-spike2  { syntax: '<number>'; inherits: true; initial-value: 1; }
@property --lp-beam-edge    { syntax: '<number>'; inherits: true; initial-value: 1; }
@keyframes lp-beam-hue-bloom {
  0%   { filter: blur(8px) hue-rotate(calc(0deg - var(--lp-beam-hue) - 10deg)) brightness(1.3) saturate(var(--lp-beam-sat)); }
  50%  { filter: blur(8px) hue-rotate(calc(var(--lp-beam-hue) + 10deg)) brightness(1.3) saturate(var(--lp-beam-sat)); }
  100% { filter: blur(8px) hue-rotate(calc(0deg - var(--lp-beam-hue) - 10deg)) brightness(1.3) saturate(var(--lp-beam-sat)); }
}
@keyframes lp-beam-travel {
  0%   { --lp-beam-x: 0.06; --lp-beam-w: 0.5; }
  10%  { --lp-beam-x: 0.15; --lp-beam-w: 0.8; }
  20%  { --lp-beam-x: 0.25; --lp-beam-w: 1.1; }
  30%  { --lp-beam-x: 0.35; --lp-beam-w: 1.3; }
  40%  { --lp-beam-x: 0.44; --lp-beam-w: 1.45; }
  50%  { --lp-beam-x: 0.5;  --lp-beam-w: 1.5; }
  60%  { --lp-beam-x: 0.56; --lp-beam-w: 1.45; }
  70%  { --lp-beam-x: 0.65; --lp-beam-w: 1.3; }
  80%  { --lp-beam-x: 0.75; --lp-beam-w: 1.1; }
  90%  { --lp-beam-x: 0.85; --lp-beam-w: 0.8; }
  100% { --lp-beam-x: 0.94; --lp-beam-w: 0.5; }
}
@keyframes lp-beam-edge-fade {
  0%    { --lp-beam-edge: 0; }
  12.5% { --lp-beam-edge: 0; }
  32.5% { --lp-beam-edge: 1; }
  67.5% { --lp-beam-edge: 1; }
  87.5% { --lp-beam-edge: 0; }
  100%  { --lp-beam-edge: 0; }
}
@keyframes lp-beam-breathe {
  0%, 100% { --lp-beam-h: 0.8; }
  25%      { --lp-beam-h: 1.25; }
  55%      { --lp-beam-h: 0.85; }
  80%      { --lp-beam-h: 1.3; }
}
@keyframes lp-beam-spike {
  0%   { --lp-beam-spike: 0.8; }
  25%  { --lp-beam-spike: 1.3; }
  50%  { --lp-beam-spike: 0.9; }
  75%  { --lp-beam-spike: 1.4; }
  100% { --lp-beam-spike: 0.8; }
}
@keyframes lp-beam-spike2 {
  0%   { --lp-beam-spike2: 1.2; }
  25%  { --lp-beam-spike2: 0.7; }
  50%  { --lp-beam-spike2: 1.4; }
  75%  { --lp-beam-spike2: 0.8; }
  100% { --lp-beam-spike2: 1.2; }
}

.lp-composer-wrap {
  --lp-beam-hue: 30deg; --lp-beam-sat: 1.8;
  --lp-beam-stroke-op: 0.3; --lp-beam-inner-op: 0.45; --lp-beam-bloom-op: 0.5;
  --lp-beam-inner-shadow: rgba(0, 0, 0, 0.14);
  position: relative; border-radius: 28px; isolation: isolate;
  animation: lp-beam-spin 1.96s linear infinite, lp-beam-fade-in 0.6s ease both;
}
[data-theme="dark"] .lp-composer-wrap {
  --lp-beam-sat: 1.2;
  --lp-beam-stroke-op: 0.26; --lp-beam-inner-op: 0.42; --lp-beam-bloom-op: 0.24;
  --lp-beam-inner-shadow: rgba(255, 255, 255, 0.27);
}
/* Border stroke — ocean blobs + a sheen, masked to the 1px ring and a rotating window. */
.lp-composer-wrap::after {
  content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none;
  border-radius: 27px; padding: 1px; clip-path: inset(0 round 28px);
  background:
    conic-gradient(from var(--lp-beam-angle),
      transparent 0%, transparent 54%,
      rgba(0, 0, 0, 0.08) 57%, rgba(0, 0, 0, 0.2) 60%, rgba(0, 0, 0, 0.4) 63%,
      rgba(0, 0, 0, 0.55) 66%, rgba(0, 0, 0, 0.4) 69%, rgba(0, 0, 0, 0.2) 72%,
      rgba(0, 0, 0, 0.08) 75%, transparent 78%, transparent 100%),
    radial-gradient(ellipse 70px 40px at 33% -7.4%, rgb(100, 80, 220), transparent),
    radial-gradient(ellipse 60px 35px at 12% -5%, rgb(60, 120, 255), transparent),
    radial-gradient(ellipse 40px 70px at 2.1% 68.3%, rgb(80, 100, 200), transparent),
    radial-gradient(ellipse 20px 35px at 2.1% 68.3%, rgb(50, 140, 220), transparent),
    radial-gradient(ellipse 180px 32px at 74.4% 100%, rgb(120, 80, 255), transparent),
    radial-gradient(ellipse 85px 26px at 55% 100%, rgb(70, 130, 255), transparent),
    radial-gradient(ellipse 74px 32px at 93.9% 0%, rgb(140, 100, 240), transparent),
    radial-gradient(ellipse 26px 42px at 100% 27.1%, rgb(90, 110, 230), transparent),
    radial-gradient(ellipse 52px 48px at 100% 27.1%, rgb(130, 70, 255), transparent);
  -webkit-mask:
    conic-gradient(from var(--lp-beam-angle),
      transparent 0%, transparent 30%,
      rgba(255, 255, 255, 0.1) 36%, rgba(255, 255, 255, 0.35) 44%,
      white 52%, white 80%,
      rgba(255, 255, 255, 0.35) 86%, rgba(255, 255, 255, 0.1) 92%,
      transparent 95%, transparent 100%),
    linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: source-in, xor;
  mask:
    conic-gradient(from var(--lp-beam-angle),
      transparent 0%, transparent 30%,
      rgba(255, 255, 255, 0.1) 36%, rgba(255, 255, 255, 0.35) 44%,
      white 52%, white 80%,
      rgba(255, 255, 255, 0.35) 86%, rgba(255, 255, 255, 0.1) 92%,
      transparent 95%, transparent 100%),
    linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  mask-composite: intersect, exclude;
  opacity: calc(var(--lp-beam-opacity) * var(--lp-beam-stroke-op));
  animation: lp-beam-hue 12s ease-in-out infinite;
}
[data-theme="dark"] .lp-composer-wrap::after {
  background:
    conic-gradient(from var(--lp-beam-angle),
      transparent 0%, transparent 54%,
      rgba(255, 255, 255, 0.1) 57%, rgba(255, 255, 255, 0.3) 60%, rgba(255, 255, 255, 0.6) 63%,
      rgba(255, 255, 255, 0.75) 66%, rgba(255, 255, 255, 0.6) 69%, rgba(255, 255, 255, 0.3) 72%,
      rgba(255, 255, 255, 0.1) 75%, transparent 78%, transparent 100%),
    radial-gradient(ellipse 70px 40px at 33% -7.4%, rgb(100, 80, 220), transparent),
    radial-gradient(ellipse 60px 35px at 12% -5%, rgb(60, 120, 255), transparent),
    radial-gradient(ellipse 40px 70px at 2.1% 68.3%, rgb(80, 100, 200), transparent),
    radial-gradient(ellipse 20px 35px at 2.1% 68.3%, rgb(50, 140, 220), transparent),
    radial-gradient(ellipse 180px 32px at 74.4% 100%, rgb(120, 80, 255), transparent),
    radial-gradient(ellipse 85px 26px at 55% 100%, rgb(70, 130, 255), transparent),
    radial-gradient(ellipse 74px 32px at 93.9% 0%, rgb(140, 100, 240), transparent),
    radial-gradient(ellipse 26px 42px at 100% 27.1%, rgb(90, 110, 230), transparent),
    radial-gradient(ellipse 52px 48px at 100% 27.1%, rgb(130, 70, 255), transparent);
}
/* Inner glow — the same ocean blobs softened inward, rotating window + edge fades. */
.lp-composer-wrap::before {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  border-radius: 28px; clip-path: inset(0 round 28px);
  background:
    radial-gradient(ellipse 63px 36px at 33% -7.4%, rgba(100, 80, 220, 0.45), transparent),
    radial-gradient(ellipse 54px 32px at 12% -5%, rgba(60, 120, 255, 0.45), transparent),
    radial-gradient(ellipse 36px 63px at 2.1% 68.3%, rgba(80, 100, 200, 0.45), transparent),
    radial-gradient(ellipse 18px 32px at 2.1% 68.3%, rgba(50, 140, 220, 0.45), transparent),
    radial-gradient(ellipse 162px 29px at 74.4% 100%, rgba(120, 80, 255, 0.45), transparent),
    radial-gradient(ellipse 77px 23px at 55% 100%, rgba(70, 130, 255, 0.45), transparent),
    radial-gradient(ellipse 67px 29px at 93.9% 0%, rgba(140, 100, 240, 0.45), transparent),
    radial-gradient(ellipse 23px 38px at 100% 27.1%, rgba(90, 110, 230, 0.45), transparent),
    radial-gradient(ellipse 47px 43px at 100% 27.1%, rgba(130, 70, 255, 0.45), transparent);
  box-shadow: inset 0 0 9px 1px var(--lp-beam-inner-shadow);
  -webkit-mask-image:
    conic-gradient(from var(--lp-beam-angle),
      transparent 0%, transparent 30%,
      rgba(255, 255, 255, 0.1) 36%, rgba(255, 255, 255, 0.35) 44%,
      white 52%, white 80%,
      rgba(255, 255, 255, 0.35) 86%, rgba(255, 255, 255, 0.1) 92%,
      transparent 95%, transparent 100%),
    linear-gradient(white, transparent 28px, transparent calc(100% - 28px), white),
    linear-gradient(to right, white, transparent 28px, transparent calc(100% - 28px), white);
  -webkit-mask-composite: source-in, source-over;
  mask-image:
    conic-gradient(from var(--lp-beam-angle),
      transparent 0%, transparent 30%,
      rgba(255, 255, 255, 0.1) 36%, rgba(255, 255, 255, 0.35) 44%,
      white 52%, white 80%,
      rgba(255, 255, 255, 0.35) 86%, rgba(255, 255, 255, 0.1) 92%,
      transparent 95%, transparent 100%),
    linear-gradient(white, transparent 28px, transparent calc(100% - 28px), white),
    linear-gradient(to right, white, transparent 28px, transparent calc(100% - 28px), white);
  mask-composite: intersect, add;
  opacity: calc(var(--lp-beam-opacity) * var(--lp-beam-inner-op));
  animation: lp-beam-hue 12s ease-in-out infinite;
}
/* Bloom — the hot white core at the beam head, blurred into the ring. */
.lp-composer-wrap .lp-beam-bloom {
  position: absolute; inset: 0; z-index: 3; pointer-events: none;
  border-radius: 27px; padding: 1px; clip-path: inset(0 round 28px);
  background: conic-gradient(from var(--lp-beam-angle),
    transparent 0%, transparent 58%,
    rgba(0, 0, 0, 0.02) 62%, rgba(0, 0, 0, 0.08) 65%, rgba(0, 0, 0, 0.2) 67%,
    rgba(0, 0, 0, 0.4) 69%, rgba(0, 0, 0, 0.6) 70%, rgba(0, 0, 0, 0.6) 70.5%,
    rgba(0, 0, 0, 0.4) 71.5%, rgba(0, 0, 0, 0.2) 73%, rgba(0, 0, 0, 0.08) 75%,
    rgba(0, 0, 0, 0.02) 78%, transparent 82%);
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  mask-composite: exclude;
  filter: blur(8px) brightness(1.3) saturate(var(--lp-beam-sat));
  opacity: calc(var(--lp-beam-opacity) * var(--lp-beam-bloom-op));
}
[data-theme="dark"] .lp-composer-wrap .lp-beam-bloom {
  background: conic-gradient(from var(--lp-beam-angle),
    transparent 0%, transparent 58%,
    rgba(255, 255, 255, 0.03) 62%, rgba(255, 255, 255, 0.08) 65%, rgba(255, 255, 255, 0.2) 67%,
    rgba(255, 255, 255, 0.45) 69%, rgba(255, 255, 255, 0.85) 70%, rgba(255, 255, 255, 0.85) 70.5%,
    rgba(255, 255, 255, 0.45) 71.5%, rgba(255, 255, 255, 0.2) 73%, rgba(255, 255, 255, 0.08) 75%,
    rgba(255, 255, 255, 0.03) 78%, transparent 82%);
}

/* ── Engaged = size "line" — once the user is inside the input (:focus-within)
   OR anywhere after the first interaction (body[data-state="chat"]), the Large
   ring swaps for the traveling Line beam: a light blob rides the bottom edge
   with breathe/spike oscillators and fades out near the corners. Same ocean
   palette, same three layers; the fade-in replay smooths the swap both ways. */
:is(.lp-composer-wrap:focus-within, body[data-state="chat"] .lp-composer-wrap) {
  --lp-beam-hue: 13deg; --lp-beam-sat: 1.95;
  animation: lp-beam-travel 3.1s linear infinite, lp-beam-edge-fade 3.1s linear infinite,
    lp-beam-breathe 4s ease-in-out infinite, lp-beam-spike 4.1s ease-in-out infinite,
    lp-beam-spike2 5.3s ease-in-out infinite, lp-beam-fade-in 0.6s ease both;
}
[data-theme="dark"] :is(.lp-composer-wrap:focus-within, body[data-state="chat"] .lp-composer-wrap) {
  --lp-beam-sat: 1.2;
  --lp-beam-stroke-op: 1.14; --lp-beam-inner-op: 0.7; --lp-beam-bloom-op: 0.8;
  --lp-beam-inner-shadow: rgba(255, 255, 255, 0.1);
}
:is(.lp-composer-wrap:focus-within, body[data-state="chat"] .lp-composer-wrap)::after {
  background:
    radial-gradient(ellipse calc(35px * var(--lp-beam-w)) calc(28px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100%) calc(100% + 2px), rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0.25) 35%, transparent 70%),
    radial-gradient(ellipse calc(45px * var(--lp-beam-w)) calc(36px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100%) calc(100% + 2px), rgb(80, 60, 200), transparent),
    radial-gradient(ellipse calc(35px * var(--lp-beam-w)) calc(32px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100% + 65px) 100%, rgb(50, 100, 220), transparent),
    radial-gradient(ellipse calc(40px * var(--lp-beam-w)) calc(28px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100% - 60px) calc(100% + 2px), rgb(70, 90, 190), transparent),
    radial-gradient(ellipse calc(35px * var(--lp-beam-w)) calc(34px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100% - 90px) 100%, rgb(110, 60, 220), transparent),
    radial-gradient(ellipse calc(38px * var(--lp-beam-w)) calc(30px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100% + 85px) calc(100% - 1px), rgb(60, 110, 230), transparent),
    radial-gradient(ellipse calc(50px * var(--lp-beam-w)) calc(24px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100% + 35px) calc(100% + 1px), rgb(100, 70, 240), transparent),
    radial-gradient(ellipse calc(40px * var(--lp-beam-w)) calc(22px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100% - 35px) 100%, rgb(80, 100, 210), transparent),
    radial-gradient(ellipse calc(35px * var(--lp-beam-w)) calc(28px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100% + 110px) calc(100% + 1px), rgb(90, 80, 225), transparent),
    radial-gradient(ellipse calc(30px * var(--lp-beam-w)) calc(30px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100% - 110px) calc(100% - 1px), rgb(120, 90, 245), transparent);
  -webkit-mask:
    radial-gradient(ellipse calc(78px * var(--lp-beam-w)) calc(60px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100%) 100%, white 0%, rgba(255, 255, 255, 0.5) 45%, transparent 100%),
    linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: source-in, xor;
  mask:
    radial-gradient(ellipse calc(78px * var(--lp-beam-w)) calc(60px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100%) 100%, white 0%, rgba(255, 255, 255, 0.5) 45%, transparent 100%),
    linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  mask-composite: intersect, exclude;
  opacity: calc(var(--lp-beam-opacity) * var(--lp-beam-edge) * var(--lp-beam-stroke-op));
}
[data-theme="dark"] :is(.lp-composer-wrap:focus-within, body[data-state="chat"] .lp-composer-wrap)::after {
  background:
    radial-gradient(ellipse calc(24px * var(--lp-beam-w)) calc(28px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100%) calc(100% + 2px), rgba(255, 255, 255, 0.38) 0%, rgba(255, 255, 255, 0.12) 30%, transparent 65%),
    radial-gradient(ellipse calc(36px * var(--lp-beam-w)) calc(36px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100%) calc(100% + 2px), rgb(100, 80, 220), transparent),
    radial-gradient(ellipse calc(30px * var(--lp-beam-w)) calc(32px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100% + 39px) 100%, rgb(60, 120, 255), transparent),
    radial-gradient(ellipse calc(33px * var(--lp-beam-w)) calc(28px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100% - 36px) calc(100% + 2px), rgb(80, 100, 200), transparent),
    radial-gradient(ellipse calc(29px * var(--lp-beam-w)) calc(34px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100% - 54px) 100%, rgb(130, 70, 255), transparent),
    radial-gradient(ellipse calc(27px * var(--lp-beam-w)) calc(30px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100% + 51px) calc(100% - 1px), rgb(70, 130, 255), transparent),
    radial-gradient(ellipse calc(36px * var(--lp-beam-w)) calc(24px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100% + 21px) calc(100% + 1px), rgb(120, 80, 255), transparent),
    radial-gradient(ellipse calc(30px * var(--lp-beam-w)) calc(22px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100% - 21px) 100%, rgb(90, 110, 230), transparent),
    radial-gradient(ellipse calc(25px * var(--lp-beam-w)) calc(28px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100% + 66px) calc(100% + 1px), rgb(110, 90, 240), transparent),
    radial-gradient(ellipse calc(23px * var(--lp-beam-w)) calc(30px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100% - 66px) calc(100% - 1px), rgb(140, 100, 255), transparent);
}
:is(.lp-composer-wrap:focus-within, body[data-state="chat"] .lp-composer-wrap)::before {
  background:
    radial-gradient(ellipse calc(33px * var(--lp-beam-w)) calc(30px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100%) 100%, rgba(100, 80, 220, 0.48), transparent),
    radial-gradient(ellipse calc(24px * var(--lp-beam-w)) calc(26px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100% + 39px) calc(100% - 3px), rgba(60, 120, 255, 0.42), transparent),
    radial-gradient(ellipse calc(27px * var(--lp-beam-w)) calc(24px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100% - 36px) 100%, rgba(80, 100, 200, 0.48), transparent),
    radial-gradient(ellipse calc(23px * var(--lp-beam-w)) calc(28px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100% - 54px) calc(100% - 2px), rgba(130, 70, 255, 0.42), transparent),
    radial-gradient(ellipse calc(24px * var(--lp-beam-w)) calc(24px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100% + 51px) calc(100% - 1px), rgba(70, 130, 255, 0.5), transparent),
    radial-gradient(ellipse calc(30px * var(--lp-beam-w)) calc(20px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100% + 21px) 100%, rgba(120, 80, 255, 0.45), transparent),
    radial-gradient(ellipse calc(25px * var(--lp-beam-w)) calc(18px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100% - 21px) calc(100% - 2px), rgba(90, 110, 230, 0.4), transparent),
    radial-gradient(ellipse calc(21px * var(--lp-beam-w)) calc(24px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100% + 66px) 100%, rgba(110, 90, 240, 0.45), transparent),
    radial-gradient(ellipse calc(18px * var(--lp-beam-w)) calc(26px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100% - 66px) calc(100% - 1px), rgba(140, 100, 255, 0.52), transparent);
  -webkit-mask-image:
    radial-gradient(ellipse calc(78px * var(--lp-beam-w)) calc(60px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100%) 100%, white 0%, rgba(255, 255, 255, 0.5) 45%, transparent 100%),
    linear-gradient(white, transparent 28px, transparent calc(100% - 28px), white),
    linear-gradient(to right, white, transparent 28px, transparent calc(100% - 28px), white);
  -webkit-mask-composite: source-in, source-over;
  mask-image:
    radial-gradient(ellipse calc(78px * var(--lp-beam-w)) calc(60px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100%) 100%, white 0%, rgba(255, 255, 255, 0.5) 45%, transparent 100%),
    linear-gradient(white, transparent 28px, transparent calc(100% - 28px), white),
    linear-gradient(to right, white, transparent 28px, transparent calc(100% - 28px), white);
  mask-composite: intersect, add;
  opacity: calc(var(--lp-beam-opacity) * var(--lp-beam-edge) * var(--lp-beam-inner-op));
}
:is(.lp-composer-wrap:focus-within, body[data-state="chat"] .lp-composer-wrap) .lp-beam-bloom {
  padding: 0;
  background:
    radial-gradient(ellipse calc(0.8px * var(--lp-beam-spike)) calc(92px * var(--lp-beam-h)) at 8% calc(100% - 2px), rgb(60, 60, 180), rgba(60, 60, 180, 0.85) 30%, transparent 88%),
    radial-gradient(ellipse calc(10px * var(--lp-beam-spike2)) calc(35px * var(--lp-beam-h)) at 22% calc(100% - 4px), rgb(80, 100, 200), rgba(80, 100, 200, 0.7) 50%, transparent 95%),
    radial-gradient(ellipse calc(2px * (2 - var(--lp-beam-spike))) calc(72px * var(--lp-beam-h)) at 36% calc(100% - 3px), rgb(50, 40, 180), rgba(50, 40, 180, 0.8) 40%, transparent 90%),
    radial-gradient(ellipse calc(14px * var(--lp-beam-spike2)) calc(28px * var(--lp-beam-h)) at 50% calc(100% - 2px), rgba(40, 80, 200, 0.7), rgba(40, 80, 200, 0.46) 55%, transparent 96%),
    radial-gradient(ellipse calc(1.2px * (2 - var(--lp-beam-spike2))) calc(85px * var(--lp-beam-h)) at 64% calc(100% - 4px), rgb(30, 50, 190), rgba(30, 50, 190, 0.82) 35%, transparent 89%),
    radial-gradient(ellipse calc(7px * var(--lp-beam-spike)) calc(45px * var(--lp-beam-h)) at 78% calc(100% - 2px), rgba(60, 90, 180, 0.7), rgba(60, 90, 180, 0.49) 48%, transparent 94%),
    radial-gradient(ellipse calc(1px * (2 - var(--lp-beam-spike))) calc(60px * var(--lp-beam-h)) at 92% calc(100% - 3px), rgb(70, 60, 200), rgba(70, 60, 200, 0.78) 42%, transparent 91%),
    radial-gradient(ellipse calc(50px * var(--lp-beam-w)) calc(32px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100%) 100%, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.18) 30%, rgba(0, 0, 0, 0.03) 60%, transparent 85%);
  -webkit-mask: radial-gradient(ellipse calc(84px * var(--lp-beam-w)) calc(110px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100%) 100%, white 0%, rgba(255, 255, 255, 0.5) 35%, transparent 100%);
  -webkit-mask-composite: source-over;
  mask: radial-gradient(ellipse calc(84px * var(--lp-beam-w)) calc(110px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100%) 100%, white 0%, rgba(255, 255, 255, 0.5) 35%, transparent 100%);
  mask-composite: add;
  opacity: calc(var(--lp-beam-opacity) * var(--lp-beam-edge) * var(--lp-beam-bloom-op));
  animation: lp-beam-hue-bloom 8s ease-in-out infinite;
}
[data-theme="dark"] :is(.lp-composer-wrap:focus-within, body[data-state="chat"] .lp-composer-wrap) .lp-beam-bloom {
  background:
    radial-gradient(ellipse calc(0.8px * var(--lp-beam-spike)) calc(92px * var(--lp-beam-h)) at 8% calc(100% - 2px), rgb(100, 120, 255), rgb(100, 120, 255) 30%, transparent 88%),
    radial-gradient(ellipse calc(10px * var(--lp-beam-spike2)) calc(35px * var(--lp-beam-h)) at 22% calc(100% - 4px), rgba(130, 100, 220, 0.98), rgba(130, 100, 220, 0.49) 50%, transparent 95%),
    radial-gradient(ellipse calc(2px * (2 - var(--lp-beam-spike))) calc(72px * var(--lp-beam-h)) at 36% calc(100% - 3px), rgb(100, 80, 255), rgb(100, 80, 255) 40%, transparent 90%),
    radial-gradient(ellipse calc(14px * var(--lp-beam-spike2)) calc(28px * var(--lp-beam-h)) at 50% calc(100% - 2px), rgba(80, 130, 220, 0.59), rgba(80, 130, 220, 0.29) 55%, transparent 96%),
    radial-gradient(ellipse calc(1.2px * (2 - var(--lp-beam-spike2))) calc(85px * var(--lp-beam-h)) at 64% calc(100% - 4px), rgb(60, 100, 255), rgb(60, 100, 255) 35%, transparent 89%),
    radial-gradient(ellipse calc(7px * var(--lp-beam-spike)) calc(45px * var(--lp-beam-h)) at 78% calc(100% - 2px), rgba(90, 120, 200, 0.91), rgba(90, 120, 200, 0.45) 48%, transparent 94%),
    radial-gradient(ellipse calc(0.6px * (2 - var(--lp-beam-spike))) calc(60px * var(--lp-beam-h)) at 92% calc(100% - 3px), rgb(120, 90, 255), rgb(120, 90, 255) 42%, transparent 91%),
    radial-gradient(ellipse calc(21px * var(--lp-beam-spike)) calc(15px * var(--lp-beam-spike2)) at calc(var(--lp-beam-x) * 100%) calc(100% + 1px), rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0.9) 20%, rgba(255, 255, 255, 0.5) 50%, transparent 100%),
    radial-gradient(ellipse calc(42px * var(--lp-beam-w)) calc(40px * var(--lp-beam-h)) at calc(var(--lp-beam-x) * 100%) 100%, rgba(255, 255, 255, 0.3) 0%, rgba(255, 255, 255, 0.12) 25%, rgba(255, 255, 255, 0.03) 55%, transparent 80%);
}
/* ── Click lap — on focus, a very fast line in the pill's idiom whips ONCE around
   the whole border (0.7s), then fades out. The layer is display:none until
   :focus-within, so the animation starts fresh on every click; blur hides it and
   re-arms the next one. Rides above every other beam layer (z-index 4). */
.lp-composer-wrap .lp-beam-lap { display: none; }
.lp-composer-wrap:focus-within .lp-beam-lap {
  display: block; position: absolute; inset: 0; z-index: 4; pointer-events: none;
  --lp-beam-lap-op: 0.5;
  border-radius: calc(28px - 3px); padding: 3px; clip-path: inset(0 round 28px);
  background:
    conic-gradient(from var(--lp-beam-angle),
      transparent 0%, transparent 54%,
      rgba(0, 0, 0, 0.08) 57%, rgba(0, 0, 0, 0.2) 60%, rgba(0, 0, 0, 0.4) 63%,
      rgba(0, 0, 0, 0.55) 66%, rgba(0, 0, 0, 0.4) 69%, rgba(0, 0, 0, 0.2) 72%,
      rgba(0, 0, 0, 0.08) 75%, transparent 78%, transparent 100%),
    radial-gradient(ellipse 70px 40px at 33% -7.4%, rgb(100, 80, 220), transparent),
    radial-gradient(ellipse 60px 35px at 12% -5%, rgb(60, 120, 255), transparent),
    radial-gradient(ellipse 40px 70px at 2.1% 68.3%, rgb(80, 100, 200), transparent),
    radial-gradient(ellipse 20px 35px at 2.1% 68.3%, rgb(50, 140, 220), transparent),
    radial-gradient(ellipse 180px 32px at 74.4% 100%, rgb(120, 80, 255), transparent),
    radial-gradient(ellipse 85px 26px at 55% 100%, rgb(70, 130, 255), transparent),
    radial-gradient(ellipse 74px 32px at 93.9% 0%, rgb(140, 100, 240), transparent),
    radial-gradient(ellipse 26px 42px at 100% 27.1%, rgb(90, 110, 230), transparent),
    radial-gradient(ellipse 52px 48px at 100% 27.1%, rgb(130, 70, 255), transparent);
  -webkit-mask:
    conic-gradient(from var(--lp-beam-angle),
      transparent 0%, transparent 44%,
      rgba(255, 255, 255, 0.1) 50%, rgba(255, 255, 255, 0.35) 57%,
      white 62%, white 74%,
      rgba(255, 255, 255, 0.35) 79%, rgba(255, 255, 255, 0.1) 84%,
      transparent 88%, transparent 100%),
    linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: source-in, xor;
  mask:
    conic-gradient(from var(--lp-beam-angle),
      transparent 0%, transparent 44%,
      rgba(255, 255, 255, 0.1) 50%, rgba(255, 255, 255, 0.35) 57%,
      white 62%, white 74%,
      rgba(255, 255, 255, 0.35) 79%, rgba(255, 255, 255, 0.1) 84%,
      transparent 88%, transparent 100%),
    linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  mask-composite: intersect, exclude;
  opacity: 0;
  animation: lp-beam-lap-spin 0.7s linear 1 both, lp-beam-lap-fade 0.7s ease-in-out 1 both;
}
[data-theme="dark"] .lp-composer-wrap:focus-within .lp-beam-lap {
  --lp-beam-lap-op: 0.6;
  background:
    conic-gradient(from var(--lp-beam-angle),
      transparent 0%, transparent 54%,
      rgba(255, 255, 255, 0.1) 57%, rgba(255, 255, 255, 0.3) 60%, rgba(255, 255, 255, 0.6) 63%,
      rgba(255, 255, 255, 0.75) 66%, rgba(255, 255, 255, 0.6) 69%, rgba(255, 255, 255, 0.3) 72%,
      rgba(255, 255, 255, 0.1) 75%, transparent 78%, transparent 100%),
    radial-gradient(ellipse 70px 40px at 33% -7.4%, rgb(100, 80, 220), transparent),
    radial-gradient(ellipse 60px 35px at 12% -5%, rgb(60, 120, 255), transparent),
    radial-gradient(ellipse 40px 70px at 2.1% 68.3%, rgb(80, 100, 200), transparent),
    radial-gradient(ellipse 20px 35px at 2.1% 68.3%, rgb(50, 140, 220), transparent),
    radial-gradient(ellipse 180px 32px at 74.4% 100%, rgb(120, 80, 255), transparent),
    radial-gradient(ellipse 85px 26px at 55% 100%, rgb(70, 130, 255), transparent),
    radial-gradient(ellipse 74px 32px at 93.9% 0%, rgb(140, 100, 240), transparent),
    radial-gradient(ellipse 26px 42px at 100% 27.1%, rgb(90, 110, 230), transparent),
    radial-gradient(ellipse 52px 48px at 100% 27.1%, rgb(130, 70, 255), transparent);
}
@keyframes lp-beam-lap-spin { to { --lp-beam-angle: 360deg; } }
@keyframes lp-beam-lap-fade {
  0%   { opacity: 0; }
  12%  { opacity: var(--lp-beam-lap-op, 0.5); }
  72%  { opacity: var(--lp-beam-lap-op, 0.5); }
  100% { opacity: 0; }
}
/* While the pill animates (a reply is streaming), the input wears NO beam at all.
   Killing the wrap's animations lets --lp-beam-opacity fall back to 0 → every layer hides. */
body.lp-busy .lp-composer-wrap { animation: none; }
body.lp-busy .lp-composer-wrap .lp-beam-lap { display: none; }
.lp-composer {
  display: block; overflow: hidden; position: relative;
  height: var(--comp-h, 54px);
  background: var(--lp-composer-bg); border: 1px solid var(--border-color); border-radius: 28px;
  box-shadow: 0 10px 34px -14px rgba(0, 0, 0, 0.3); cursor: text;
  transition: height 0.45s cubic-bezier(0.22, 1, 0.36, 1), border-color 0.25s ease;
}
/* The real Google-AI-Mode spring — a sampled linear() curve captured from their
   composer. Progressive-enhancement: browsers without linear() keep the
   cubic-bezier fallback above. This is the exact expand/collapse feel. */
@supports (transition-timing-function: linear(0, 1)) {
  .lp-composer {
    transition-duration: 0.6s;
    transition-timing-function: linear(0 0%, 0.00245 1.753%, 0.00994 3.55%, 0.03415 6.402%, 0.07441 9.061%, 0.12808 11.414%, 0.19399 13.366%, 0.27138 14.974%, 0.34474 16.052%, 0.47679 17.475%, 0.60689 19.389%, 0.68967 21.461%, 0.74193 23.444%, 0.78755 25.874%, 0.82719 28.791%, 0.86492 32.632%, 0.88332 35.056%, 0.9039 38.373%, 0.9295 43.795%, 0.95333 50.97%, 0.97199 59.335%, 0.9858 69.036%, 0.99492 80.205%, 1 100%);
  }
}
[data-theme="dark"] .lp-composer { box-shadow: 0 10px 34px -14px rgba(0, 0, 0, 0.6); }
body.kb-room .lp-composer { box-shadow: none; }
.lp-composer-row1 { display: flex; align-items: center; min-height: 54px; padding: 0 14px 0 16px; }
.lp-composer-pill { flex: 1 1 auto; display: flex; align-items: center; gap: 6px; color: var(--text-tertiary); font-family: var(--font-system); }
.lp-composer-input {
  flex: 1 1 auto; min-width: 0; border: none; background: transparent; outline: none; resize: none; display: block;
  font-family: var(--font-system); font-size: 16px; line-height: 22px; color: var(--text-primary);
  max-height: 96px; padding: 0;
}
.lp-composer-input::placeholder { color: var(--text-tertiary); }
.lp-composer-tools { display: flex; align-items: center; justify-content: space-between; padding: 2px 10px 10px 12px; opacity: 0; transition: opacity 0.25s ease 0.08s; }
.lp-composer.expanded .lp-composer-tools { opacity: 1; }
.lp-tools-left { display: inline-flex; align-items: center; gap: 8px; }
.lp-composer-plus {
  flex: 0 0 auto; width: 34px; height: 34px; border-radius: 50%;
  border: 1px solid var(--border-color); background: transparent; color: var(--text-secondary);
  display: flex; align-items: center; justify-content: center; font-size: 0.95rem; cursor: pointer;
}
/* Respect [hidden] — the display:flex above was overriding it, so the phone-mode Cancel "×"
   leaked into the chat composer. Now it only appears during phone signup. */
.lp-composer-plus[hidden] { display: none !important; }
.lp-send {
  flex: 0 0 auto; width: 34px; height: 34px; border-radius: 50%; border: none;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--bg-bubble-user); color: var(--bg-bubble-user-text); cursor: pointer; font-size: 0.85rem;
  transition: transform var(--transition-fast), opacity var(--transition-fast);
}
.lp-send:disabled { opacity: 0.35; pointer-events: none; }
.lp-send:active { transform: scale(0.9); }

/* Mic in the tools row — pulses red while dictating. */
.lp-dictate.recording { color: #d8463a; border-color: #d8463a; animation: lp-rec-pulse 1.4s ease-in-out infinite; }
@keyframes lp-rec-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(216, 70, 58, 0.35); }
  50%      { box-shadow: 0 0 0 6px rgba(216, 70, 58, 0); }
}

/* File picker — MUST NOT be display:none. iOS Safari silently ignores
   programmatic .click() on display:none / [hidden] file inputs. */
.lp-file-input {
  position: fixed; left: 0; top: 0; width: 1px; height: 1px;
  opacity: 0; overflow: hidden; z-index: -1; pointer-events: none;
}

/* Attached-image preview row (top of the expanded composer). */
.lp-attach { display: flex; align-items: center; gap: 8px; padding: 10px 14px 0 16px; }
.lp-attach[hidden] { display: none; }
.lp-attach-frame {
  position: relative; flex: 0 0 auto; border-radius: 12px; isolation: isolate;
  line-height: 0;
}
/* Blue comet ring — the classic waivy blue palette — spins while HEIC converts. */
.lp-attach-frame::before {
  content: ""; position: absolute; inset: -2.5px; z-index: -1; border-radius: 13px;
  background: conic-gradient(from 180deg,
    #6ea2f0 0deg, #4079e0 18deg, #2f5fc4 40deg, #274fa8 70deg,
    rgba(39, 79, 168, 0) 110deg, rgba(39, 79, 168, 0) 360deg);
  opacity: 0; pointer-events: none;
}
.lp-attach-frame.is-loading::before {
  opacity: 1; animation: lp-attach-spin 1.15s linear infinite;
}
@keyframes lp-attach-spin { to { transform: rotate(360deg); } }
.lp-attach-thumb {
  height: 52px; width: auto; max-width: 120px; min-width: 52px;
  object-fit: cover; border-radius: 10px; border: 1px solid var(--border-color);
  display: block; background: color-mix(in srgb, var(--text-primary) 6%, var(--lp-composer-bg, #fff));
}
.lp-attach-frame.is-loading .lp-attach-thumb {
  width: 70px; height: 52px; border-color: transparent;
  /* Soft shimmer inside the placeholder while the ring spins. */
  background:
    linear-gradient(110deg,
      color-mix(in srgb, var(--text-primary) 5%, var(--lp-composer-bg, #fff)) 30%,
      color-mix(in srgb, #6ea2f0 18%, var(--lp-composer-bg, #fff)) 48%,
      color-mix(in srgb, var(--text-primary) 5%, var(--lp-composer-bg, #fff)) 66%);
  background-size: 200% 100%;
  animation: lp-attach-shimmer 1.4s ease-in-out infinite;
}
@keyframes lp-attach-shimmer {
  0% { background-position: 100% 0; }
  100% { background-position: -100% 0; }
}
.lp-attach-x {
  width: 22px; height: 22px; border-radius: 50%; border: none;
  background: color-mix(in srgb, var(--text-primary) 10%, transparent); color: var(--text-secondary);
  font-size: 0.7rem; cursor: pointer; display: inline-flex; align-items: center; justify-content: center;
}
/* A sent image inside a user bubble. */
.lp-bubble .lp-bubble-img { display: block; max-width: 200px; border-radius: 12px; margin: 2px 0 6px; }
/* A generated/edited OR sent image renders larger than an upload thumbnail, and BARE (no box). */
.lp-bubble-img-gen { max-width: min(300px, 78vw); width: 100%; border-radius: 16px; margin: 0; display: block; }
/* An image with no caption drops the bubble box entirely — just the image floats. */
.lp-bubble.lp-img-only { background: transparent; padding: 0; box-shadow: none; border: none; max-width: 78%; }
/* A SENT image (user) — bare image, right-aligned, with any caption bubble stacked beneath it. */
.lp-sent { display: flex; flex-direction: column; align-items: flex-end; gap: 5px; max-width: 78%; }
.lp-bubble-img { cursor: pointer; }   /* tap to open fullscreen */

/* ── Fullscreen image viewer (lightbox) ─────────────────────────────────────── */
.lp-lightbox {
  position: fixed; inset: 0; z-index: 100; padding: 24px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 20px;
  background: rgba(8, 10, 14, 0.96); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  animation: chat-fade-in 0.16s ease-out both;
}
.lp-lightbox[hidden] { display: none; }
.lp-lightbox-img { max-width: 92vw; max-height: 72vh; border-radius: 14px; object-fit: contain; box-shadow: 0 24px 70px rgba(0, 0, 0, 0.55); }
.lp-lightbox-bar { display: flex; gap: 12px; }
.lp-lightbox-btn { padding: 11px 26px; border-radius: 999px; border: none; background: rgba(255, 255, 255, 0.16); color: #fff; font: inherit; font-weight: 600; cursor: pointer; }
.lp-lightbox-btn:active { background: rgba(255, 255, 255, 0.3); }
.lp-lightbox-close {
  position: absolute; top: calc(16px + env(safe-area-inset-top)); right: 18px; width: 40px; height: 40px;
  border-radius: 50%; border: none; background: rgba(255, 255, 255, 0.16); color: #fff;
  display: flex; align-items: center; justify-content: center; cursor: pointer;
}
body.lp-lightbox-open { overflow: hidden; }

/* Content wash while the composer is focused (Google's ~60% scrim). Extends
   well past the viewport bottom so the keyboard pan never exposes a hard edge. */
.lp-dim {
  position: fixed; top: 0; left: 0; right: 0; bottom: -45vh; z-index: 5;
  background: color-mix(in srgb, var(--bg-app) 62%, transparent);
  opacity: 0; pointer-events: none; transition: opacity 0.2s ease;
}
body.composer-dim .lp-dim { opacity: 1; pointer-events: auto; }

/* ── Phone / signup mode — the composer BECOMES the phone field ──────────────
   The Get-started CTA (or typing a number) flips the composer into phone mode:
   a tappable country-code prefix + the iMessage/WhatsApp value-prop, riding the
   keyboard natively. The country menu opens UPWARD, above the keyboard. */
.lp-composer.pm { overflow: visible; }                       /* let the upward country menu escape */
.lp-composer.pm .lp-tools-left #wv-attach-btn,
.lp-composer.pm .lp-tools-left #wv-mic { display: none; }    /* image/mic swap out for the country prefix */
.lp-phone-cc { position: relative; display: inline-flex; }
.lp-phone-cc[hidden] { display: none; }
.lp-pm-prefix {
  display: inline-flex; align-items: center; gap: 7px; height: 34px; padding: 0 13px;
  border-radius: 999px; border: 1px solid var(--border-color); background: transparent; cursor: pointer;
  font-family: var(--font-system); font-size: 0.95rem; color: var(--text-primary); font-variant-numeric: tabular-nums;
}
.lp-pm-prefix .flag { font-size: 1.05rem; line-height: 1; }
.lp-pm-prefix .lp-chev { width: 9px; height: 9px; color: var(--text-tertiary); }
/* In signup mode the greeting + suggestion chips fold away (it's a form now). */
body.pm-signup .lp-dock-chips, body.pm-signup .lp-hero { opacity: 0 !important; pointer-events: none !important; }

/* ── Country-code menu (searchable, opens upward from the prefix) ──────────── */
.lp-cc-menu {
  position: absolute; z-index: 40; top: auto; bottom: calc(100% + 10px); left: 0; right: auto;
  width: min(320px, calc(100vw - 56px));
  background: var(--bg-app); border: 1.5px solid var(--border-color); border-radius: 14px;
  box-shadow: 0 22px 55px -22px rgba(0, 0, 0, 0.5); overflow: hidden; display: none;
}
.lp-cc-menu.open { display: block; animation: chat-fade-in 0.16s ease-out both; }
.lp-cc-search {
  width: 100%; border: none; border-bottom: 1px solid var(--border-color);
  padding: 13px 16px; font-size: 16px; background: transparent; color: var(--text-primary);
  font-family: var(--font-system); outline: none; box-sizing: border-box;
}
.lp-cc-list { max-height: 240px; overflow-y: auto; -webkit-overflow-scrolling: touch; }
.lp-cc-opt {
  display: flex; align-items: center; gap: 10px; width: 100%; padding: 11px 16px;
  border: none; background: none; cursor: pointer;
  font-family: var(--font-system); font-size: 0.95rem; color: var(--text-primary); text-align: left;
}
.lp-cc-opt:hover { background: color-mix(in srgb, var(--bg-bubble-user) 10%, transparent); }
.lp-cc-opt .flag { font-size: 1.15rem; line-height: 1; }
.lp-cc-opt .name { flex: 1; }
.lp-cc-opt .dial { color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.lp-cc-empty { padding: 16px; text-align: center; color: var(--text-tertiary); font-size: 0.9rem; }

@media (prefers-reduced-motion: reduce) {
  /* Still the beam: with the wrap oscillators off, --lp-beam-opacity stays 0 → all layers hidden. */
  .lp-typing-wrap, .lp-composer-wrap,
  .lp-typing-wrap::after, .lp-typing-wrap .lp-beam-bloom,
  .lp-composer-wrap::before, .lp-composer-wrap::after, .lp-composer-wrap .lp-beam-bloom,
  .lp-composer-wrap .lp-beam-lap { animation: none !important; }
  .lp-bubble, .lp-typing, .lp-dock, .lp-hero, .lp-dock-chips { animation: none !important; transition: none !important; }
}

/* ── ADL new components ──────────────────────────────────────────────────── */

/* Source chip — inline attribution appended to prose bubbles */
.lp-src-chip {
  display: inline-flex; align-items: center; gap: 5px;
  background: var(--wv-chip-tint); border-radius: 10px;
  font-size: 11px; padding: 2px 8px; white-space: nowrap;
  color: var(--text-secondary); border: none; cursor: pointer;
  position: relative; margin-left: 5px; vertical-align: middle;
}
span.lp-src-chip { cursor: default; }
.lp-src-dot { color: var(--text-tertiary); }
.lp-src-fav { width: 14px; height: 14px; border-radius: 50%; flex: none; display: block; }
.lp-src-pop {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 50;
  background: var(--bg-app); border: 1px solid var(--wv-hairline);
  border-radius: 10px; box-shadow: 0 8px 24px rgba(0,0,0,0.15);
  padding: 8px 10px; min-width: 160px; display: flex; flex-direction: column; gap: 6px;
}
.lp-src-pop[hidden] { display: none; }
.lp-src-pop-link {
  display: flex; align-items: center; gap: 7px;
  font-size: 12px; color: var(--text-primary); text-decoration: none; white-space: nowrap;
}
.lp-src-pop-link:hover { color: var(--wv-accent); }
/* Source-chip expansion — the full two-column source grid inline on desktop (below the lead). */
.lp-src-grid { display: block; width: 100%; max-width: 560px; min-width: 0; box-sizing: border-box; margin-top: 24px; padding-top: 16px; border-top: 1px solid var(--wv-hairline); animation: chat-fade-in 0.35s ease both; }
.lp-src-grid[hidden] { display: none; }
.lp-src-grid .lp-sources-label { margin: 0 0 6px 2px; }
.lp-row.waivy .lp-bubble:has(.lp-src-grid),
.lp-row.waivy .lp-bubble:has(.lp-sources-wrap) { width: 560px; }
/* Source-chip expansion in the mobile bottom sheet — single column. */
.lp-sheet-sources { padding: 4px 2px 8px; }
.lp-sheet-sources .lp-sources { grid-template-columns: 1fr; }
.lp-sheet-sources .lp-sources-label { margin: 0 0 8px 2px; }

/* Deepen — distinct next-step controls, not editorial links inside a sentence. */
.lp-row.waivy .lp-bubble:has(.lp-deepen) { width: 100%; max-width: 100%; min-width: 0; }
.lp-deepen { width: 100%; max-width: 100%; min-width: 0; box-sizing: border-box; border-top: 1px solid var(--wv-hairline); margin-top: 4px; padding-top: 14px; font-size: 14px; color: var(--text-secondary); }
.lp-deepen-lead { display: block; margin-bottom: 9px; color: var(--text-secondary); font-weight: 600; }
.lp-deepen-actions { display: flex; flex-wrap: wrap; gap: 8px; min-width: 0; }
.lp-deepen-link {
  min-width: 0; max-width: 100%; box-sizing: border-box; white-space: normal; overflow-wrap: anywhere; text-align: left;
  font: 600 13px/1.25 var(--font-system); color: var(--text-primary);
  background: var(--wv-panel-tint); border: 1px solid var(--wv-hairline); border-radius: 999px;
  cursor: pointer; padding: 8px 12px; -webkit-tap-highlight-color: transparent;
}
.lp-deepen-link:hover { border-color: var(--wv-link-underline); background: var(--bg-app); }
.lp-deepen-link:active { opacity: 0.6; }
/* In-text follow-up links (the closing offer's branches) — underlined and tappable,
   same send as the chips. white-space: normal overrides the chip row's nowrap. */
.lp-fq { display: inline-block; max-width: 100%; color: var(--text-primary); font-size: 0.9em; line-height: 1.25; font-weight: 600; text-decoration: none; cursor: pointer; white-space: normal; padding: 4px 8px; margin: 2px; border: 1px solid var(--wv-hairline); border-radius: 999px; }
.lp-fq:hover { color: var(--wv-accent); }
.lp-fq:active { opacity: 0.6; }
@media (max-width: 560px) {
  .lp-deepen-actions { flex-direction: column; }
  .lp-deepen-link { width: 100%; border-radius: 12px; }
}
/* Google-AI-Mode overlapping favicon stack — in the progress pill and the "N sites" row. */
.lp-favstack { display: inline-flex; align-items: center; }
.lp-favstack img { width: 18px; height: 18px; border-radius: 50%; border: 2px solid var(--bg-app); background: #fff; margin-left: -6px; object-fit: cover; }
.lp-favstack img:first-child { margin-left: 0; }
.lp-sites-row { display: flex; align-items: center; gap: 8px; margin: 4px 0 10px 12px; }
.lp-sites-n { font-size: 13px; color: var(--text-secondary); }
/* the pill's strip is the same stack, smaller */
.lp-fav-strip { display: inline-flex; align-items: center; flex: 0 0 auto; min-width: 0; }
.lp-fav-strip[hidden] { display: none; }
.lp-fav-strip .lp-favstack img { width: 14px; height: 14px; border-width: 1.5px; margin-left: -5px; }

/* Ranked rows (replaces medal table) */
.lp-rank-rows { display: block; }
.lp-rank-row {
  display: flex; align-items: baseline; gap: 12px;
  padding: 11px 0; border-bottom: 1px solid var(--wv-hairline); font-size: 14px;
}
.lp-rank-row:last-child { border-bottom: none; }
.lp-rank-num { width: 14px; flex: none; font-weight: 700; color: var(--text-tertiary); font-variant-numeric: tabular-nums; }
.lp-rank-name { flex: 1; min-width: 0; }
.lp-rank-qual { color: var(--text-tertiary); }
.lp-rank-val { font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Place status badge (Open / Closed) in the place row */
.lp-place-status { font-size: 12px; font-weight: 600; margin-left: auto; white-space: nowrap; flex: none; }
.lp-place-status.is-open { color: var(--wv-up); }
.lp-place-status.is-closed { color: var(--text-secondary); }
.lp-place-desc { font-size: 0.78rem; color: var(--text-secondary); margin-top: 1px; display: block; }

/* ADL chart panel — big value + direction pill above the SVG sparkline */
.lp-chart-panel { background: var(--wv-panel-tint); border-radius: 14px; padding: 14px 16px; }
.lp-chart-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; }
.lp-chart-val { font-size: 26px; font-weight: 600; font-variant-numeric: tabular-nums; }
@media (max-width: 480px) { .lp-chart-val { font-size: 22px; } }
.lp-chart-pill { border-radius: 12px; padding: 2px 9px; font-size: 12px; font-weight: 600; }
.lp-chart-up { background: color-mix(in srgb, var(--wv-up) 14%, transparent); color: var(--wv-up); }
.lp-chart-down { background: color-mix(in srgb, var(--wv-down) 14%, transparent); color: var(--wv-down); }
.lp-chart-range { font-size: 11px; color: var(--text-tertiary); margin-left: auto; }

/* ── Scatter / frontier map — labeled points + optional frontier polyline ───── */
.lp-scat-svg { display: block; width: 100%; height: auto; }
.lp-scat-grid { stroke: var(--border-color); stroke-width: 0.25; }
.lp-scat-frontier { fill: none; stroke: #4079e0; stroke-width: 0.6; opacity: 0.75; }
.lp-scat-pt { fill: #4079e0; }
.lp-scat-dom { fill: #a3a8b0; }
[data-theme="dark"] .lp-scat-dom { fill: #6b7280; }
.lp-scat-name { font-size: 3px; fill: var(--text-secondary); }
.lp-scat-tick { font-size: 2.8px; fill: var(--text-tertiary); font-variant-numeric: tabular-nums; }
.lp-scat-axis { font-size: 3.1px; fill: var(--text-tertiary); }
.lp-scat-legend { display: flex; align-items: center; gap: 5px; margin-top: 8px; font-size: 11px; color: var(--text-tertiary); }
.lp-scat-key { width: 7px; height: 7px; border-radius: 999px; display: inline-block; margin-left: 8px; }
.lp-scat-key:first-child { margin-left: 0; }
.lp-scat-key-pt { background: #4079e0; }
.lp-scat-key-dom { background: #a3a8b0; }

/* Status card row */
.lp-status { display: flex; gap: 10px; align-items: baseline; font-size: 14.5px; line-height: 21px; }
.lp-status-word { font-weight: 700; white-space: nowrap; }
.lp-status-ok { color: var(--wv-up); }
.lp-status-action, .lp-status-down { color: var(--wv-down); }
.lp-status-pending { color: var(--text-tertiary); }

/* Code block */
.lp-code {
  background: var(--wv-panel-tint); border-radius: 10px; padding: 14px 16px;
  font-family: "JetBrains Mono", ui-monospace, Menlo, monospace;
  font-size: 12.5px; line-height: 20px; white-space: pre-wrap;
  overflow-wrap: anywhere; margin: 0;
  font-variant-ligatures: none;   /* keep `==`, `->`, `!=` literal in code */
}
.lp-code code { background: none; padding: 0; font: inherit; }

/* Panel diagram bubble (adapter adds .lp-diagram to the mono bubble) */
.lp-bubble.lp-diagram {
  background: var(--wv-panel-tint); border-radius: 10px; padding: 14px 16px;
  font-family: "JetBrains Mono", ui-monospace, Menlo, monospace;
  font-size: 12.5px; line-height: 20px; white-space: pre;
  overflow-x: auto; border: none;
}

/* Vault (hidden-rows expand) */
.lp-vault-toggle {
  display: flex; justify-content: space-between; align-items: center;
  width: 100%; background: var(--wv-panel-tint); border: none; border-radius: 10px;
  padding: 11px 14px; font-size: 13.5px; font-weight: 600; color: var(--text-primary);
  cursor: pointer; margin-top: 10px;
}
.lp-vault-caret { color: var(--text-tertiary); }
.lp-vault-body { margin-top: 8px; }

/* ── Scoreboard card (server-built sports rows) ──────────────────────────────
   Glance order: Live → Final → Upcoming sections; per game two aligned side rows
   (team left, score right, winner bold), status pill top-right, scorers below. */
.lp-sb { display: block; }
.lp-sb-sec {
  font-size: 10.5px; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--text-tertiary); font-weight: 700; margin: 14px 0 2px;
}
.lp-sb-sec:first-child { margin-top: 0; }
.lp-sb-game { padding: 8px 6px; border-top: 1px solid var(--wv-hairline); border-radius: 8px; }
.lp-sb-sec + .lp-sb-game { border-top: none; }
.lp-sb-me { background: var(--wv-hl-tint); }
/* Multi-game slates lay out as a responsive grid of soft tiles (2-up on phones, more on
   desktop) so a full day's card uses the width instead of running long vertically. */
.lp-sb-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 162px), 1fr));
  gap: 8px 12px; align-items: start;
}
.lp-sb-grid .lp-sb-game { border-top: none; padding: 9px 11px; background: var(--wv-panel-tint); }
.lp-sb-grid .lp-sb-me { background: var(--wv-hl-tint); }
/* The answer bubble is a shrink-to-fit flex item; a multi-game grid must fill the answer
   column (a DEFINITE width) or auto-fill collapses to a single stacked column. Scoped to the
   grid so a single-game hero still hugs its content. */
.lp-row.waivy .lp-bubble:has(.lp-sb-grid) { width: 100%; }
.lp-sb-top { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin-bottom: 3px; }
.lp-sb-top:empty { display: none; }
.lp-sb-stage { font-size: 11.5px; color: var(--text-tertiary); font-weight: 600; }
.lp-sb-status { font-size: 11.5px; color: var(--text-tertiary); font-weight: 600; white-space: nowrap; margin-left: auto; }
.lp-sb-live { color: var(--wv-down); display: inline-flex; align-items: center; gap: 5px; }
.lp-sb-live::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor;
  animation: lp-sb-pulse 1.6s ease-in-out infinite;
}
@keyframes lp-sb-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } }
.lp-sb-side { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; padding: 2.5px 0; }
.lp-sb-team { color: var(--text-secondary); font-size: 14.5px; min-width: 0; }
.lp-sb-rec { font-size: 11px; color: var(--text-tertiary); margin-left: 6px; font-variant-numeric: tabular-nums; white-space: nowrap; }
.lp-sb-score { font-variant-numeric: tabular-nums; font-weight: 600; font-size: 14.5px; color: var(--text-secondary); white-space: nowrap; }
.lp-sb-win .lp-sb-team, .lp-sb-win .lp-sb-score { color: var(--text-primary); font-weight: 700; }
.lp-sb-scorers { font-size: 12px; color: var(--text-tertiary); margin-top: 2px; }
.lp-sb-logo { width: 17px; height: 17px; object-fit: contain; vertical-align: -4px; margin-right: 6px; }
/* Single game → the hero: answer readable at arm's length */
.lp-sb-hero .lp-sb-game { border-top: none; padding: 4px 2px 2px; }
.lp-sb-hero .lp-sb-team { font-size: 17px; }
.lp-sb-hero .lp-sb-score { font-size: 26px; font-weight: 700; }
.lp-sb-hero .lp-sb-status { font-size: 12.5px; }
.lp-sb-hero .lp-sb-scorers { font-size: 13px; margin-top: 4px; }

/* Racing next-event card — structured fields stay readable on narrow phones. */
.lp-event-card {
  padding: 12px 14px; border-radius: 12px; background: var(--wv-card-bg, #f6f3ec);
}
.lp-event-name { color: var(--text-primary); font-size: 16px; font-weight: 700; margin-bottom: 8px; }
.lp-event-detail {
  display: grid; grid-template-columns: 52px minmax(0, 1fr); gap: 10px;
  align-items: baseline; padding: 3px 0; font-size: 13px;
}
.lp-event-detail span { color: var(--text-tertiary); }
.lp-event-detail b { color: var(--text-secondary); font-weight: 600; overflow-wrap: break-word; }
.lp-event-detail:last-child b { white-space: nowrap; }

/* ── Scorecard hero (server-built) — Google-style two-team card: away | center | home ── */
.lp-sc {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 10px;
  padding: 14px 6px 10px; background: var(--wv-card-bg, #f6f3ec); border-radius: 14px;
}
.lp-sc-team { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 3px; min-width: 0; }
.lp-sc-logo { width: 44px; height: 44px; object-fit: contain; }
.lp-sc-logo-none { width: 44px; height: 44px; }
.lp-sc-flag { font-size: 34px; line-height: 44px; }
.lp-sc-name { font-size: 13.5px; font-weight: 600; color: var(--text-primary); overflow-wrap: anywhere; }
.lp-sc-rec { font-size: 11.5px; color: var(--text-tertiary); font-variant-numeric: tabular-nums; }
.lp-sc-score { font-size: 40px; font-weight: 700; line-height: 1.05; color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.lp-sc-teamwin .lp-sc-name { font-weight: 700; }
.lp-sc-score.lp-sc-win { color: var(--text-primary); }
.lp-sc-center { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 2px; padding: 0 4px; }
.lp-sc-time { font-size: 21px; font-weight: 700; color: var(--text-primary); white-space: nowrap; }
.lp-sc-status { font-size: 13px; font-weight: 700; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 0.03em; }
.lp-sc-status.lp-sc-live { color: #d0342c; }
.lp-sc-date { font-size: 12px; color: var(--text-tertiary); }
.lp-sc-stage { font-size: 12px; color: var(--text-tertiary); }
.lp-sc-result { font-size: 12.5px; color: var(--text-secondary); font-weight: 600; }
@media (max-width: 460px) {
  .lp-sc-logo, .lp-sc-logo-none { width: 38px; height: 38px; }
  .lp-sc-score { font-size: 32px; }
  .lp-sc-time { font-size: 18px; }
}

/* ── Standings table (server-built) — ranked, tabular, cut line + my team ── */
/* Fixed-width numeric columns (table-layout: fixed honors header widths) so the table
   stays at card width on a phone — nowrap numerics otherwise push GB past the edge.
   border-box so the widths INCLUDE the cell padding (content-box made the sum exceed
   the table width and crushed the team column to its min-content). */
.lp-standings .lp-st-rank { width: 34px; padding-right: 4px; color: var(--text-tertiary); font-variant-numeric: tabular-nums; }
.lp-standings th, .lp-standings td { box-sizing: border-box; }
.lp-standings .lp-td-num { width: 46px; }
.lp-standings .lp-st-team { font-weight: 600; color: var(--text-primary); }
.lp-standings tbody tr.lp-st-me > * { background: var(--wv-hl-tint); }
.lp-standings tbody tr.lp-st-me .lp-st-team { color: var(--wv-accent); }
.lp-standings tbody tr.lp-st-cut > * { border-bottom: 2px solid var(--wv-rule-strong); }
.lp-standings td, .lp-standings th { padding-left: 8px; }
.lp-standings td.lp-td-num:first-of-type, .lp-standings th.lp-td-num:first-of-type { padding-left: 14px; }

/* ── Box score card — scoreline hero + per-team stat tables, sticky player col ── */
.lp-bx-hero { margin-bottom: 6px; }
.lp-bx-team { margin-top: 10px; }
.lp-bx-team:first-of-type { margin-top: 0; }
.lp-bx-name { font-size: 13px; font-weight: 700; color: var(--text-primary); margin: 14px 0 2px; }
.lp-bx-team:first-of-type .lp-bx-name { margin-top: 4px; }
.lp-bx-cat {
  font-size: 10.5px; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--text-tertiary); font-weight: 700; margin: 10px 0 2px;
}
.lp-bx-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.lp-bx .lp-table { min-width: 540px; }   /* the TABLE scrolls inside .lp-bx-scroll — never widen the card/page */
.lp-bx .lp-bx-player {
  position: sticky; left: 0; z-index: 1; background: var(--bg-app);
  max-width: 150px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.lp-bx-extra { display: none; }
.lp-bx-show .lp-bx-extra { display: table-row; }
.lp-bx-more {
  border: none; background: none; padding: 7px 0 0; cursor: pointer;
  font-size: 12.5px; font-weight: 600; color: var(--wv-accent); font-family: inherit;
}
.lp-bx-more:active { opacity: 0.6; }

/* ── Quote hero (single-ticker Financial Summary without a sparkline) ── */
.lp-quote-hero { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin: 2px 0 12px; }
.lp-quote-sym { font-size: 13px; font-weight: 700; letter-spacing: 0.03em; color: var(--text-tertiary); text-transform: uppercase; }
.lp-quote-price { font-size: 26px; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--text-primary); }
@media (max-width: 480px) { .lp-quote-price { font-size: 22px; } }
.lp-rich-finance { padding: 16px 18px 17px; border: 1px solid var(--wv-hairline); border-radius: 16px; background: color-mix(in srgb, var(--bg-app) 94%, var(--wv-hl-tint)); }
.lp-rich-finance .lp-rich-label { margin-bottom: 2px; font-size: 16px; }
.lp-rich-finance .lp-table { font-size: var(--wv-answer-data-size); }
.lp-rich-finance .lp-table th, .lp-rich-finance .lp-table td { padding-top: 9px; padding-bottom: 9px; }
.lp-fin-meta { color: var(--text-tertiary); font-size: 11.5px; line-height: 1.35; margin-bottom: 10px; }
.lp-fin-freshness { color: var(--text-secondary); font-size: 12px; line-height: 1.45; margin: -4px 0 12px; }
.lp-fin-freshness-compare { display: grid; gap: 3px; margin: 2px 0 12px; }
.lp-fin-freshness-compare strong { color: var(--text-primary); font-weight: 650; }
.lp-fin-history { margin: 4px 0 12px; transition: opacity 140ms ease; }
.lp-fin-history[aria-busy="true"] { opacity: 0.62; }
.lp-fin-plot { position: relative; height: 112px; width: 100%; }
.lp-fin-spark { display: block; width: 100%; height: 112px; overflow: visible; color: var(--text-primary); }
.lp-fin-gridline { fill: none; stroke: var(--wv-hairline); stroke-width: 1; stroke-dasharray: 3 4; vector-effect: non-scaling-stroke; }
.lp-fin-prevline { stroke: var(--text-secondary); opacity: .58; }
.lp-fin-prev-label, .lp-fin-scale { position: absolute; z-index: 1; padding: 1px 4px; border-radius: 4px; background: color-mix(in srgb, var(--bg-app) 82%, transparent); color: var(--text-secondary); font: 600 10.5px/1.25 var(--font-system); pointer-events: none; }
.lp-fin-prev-label { left: 6px; transform: translateY(-50%); }
.lp-fin-scale { right: 4px; }
.lp-fin-scale-hi { top: 3px; }
.lp-fin-scale-lo { bottom: 3px; }
.lp-fin-time { display: flex; justify-content: space-between; margin-top: 4px; color: var(--text-secondary); font: 500 12px/1.3 var(--font-system); }
.lp-fin-sparkline { fill: none; stroke: currentColor; stroke-width: 2.25; stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke; stroke-dasharray: 1; stroke-dashoffset: 1; animation: lp-fin-line-draw 720ms cubic-bezier(.22,.8,.3,1) forwards; }
.lp-fin-sparkdot { fill: currentColor; vector-effect: non-scaling-stroke; opacity: 0; animation: lp-fin-dot-in 180ms ease 650ms forwards; }
/* The dash reveal is only length-accurate because the viewBox is fitted 1:1 to the pixel box
   (fitFinanceSparks in waivy-ui.js): non-scaling-stroke measures dashes in screen space while
   pathLength normalizes them in user space, so any scale != 1 truncates the line short of the
   end dot. Dropping the dash once the draw lands makes the settled line immune to that.
   That swap sits at 99.9%, NOT in `to` — a length-list → `none` interpolation is DISCRETE, so
   on the final keyframe alone it would pop the line to full length at the animation's midpoint. */
@keyframes lp-fin-line-draw {
  from { stroke-dashoffset: 1; stroke-dasharray: 1; }
  99.9% { stroke-dashoffset: 0; stroke-dasharray: 1; }
  to { stroke-dashoffset: 0; stroke-dasharray: none; }
}
@keyframes lp-fin-dot-in { to { opacity: 1; } }
.lp-fin-spark.is-static .lp-fin-sparkline { animation: none; stroke-dasharray: none; stroke-dashoffset: 0; }
.lp-fin-spark.is-static .lp-fin-sparkdot { animation: none; opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .lp-fin-sparkline { animation: none; stroke-dasharray: none; stroke-dashoffset: 0; }
  .lp-fin-sparkdot { animation: none; opacity: 1; }
}
.lp-fin-line-up { color: var(--wv-up, #128a4b); }
.lp-fin-line-down { color: var(--wv-down, #c8463a); }
.lp-fin-ranges {
  display: flex; align-items: center; gap: 3px; overflow-x: auto; scrollbar-width: none;
  box-sizing: border-box; width: calc(100% + 36px); margin: 4px -18px 0; padding: 0 18px 1px;
}
.lp-fin-ranges::-webkit-scrollbar { display: none; }
.lp-fin-range { flex: 1 0 44px; min-width: 44px; min-height: 44px; appearance: none; border: 1px solid transparent; border-radius: 999px; background: transparent; color: var(--text-secondary); font: 600 13px/1 var(--font-system); padding: 10px 9px; cursor: pointer; }
.lp-fin-range:hover { color: var(--text-primary); background: color-mix(in srgb, var(--text-primary) 6%, transparent); }
.lp-fin-range.is-active { color: var(--text-primary); border-color: var(--wv-rule-strong); background: color-mix(in srgb, var(--text-primary) 10%, transparent); }
.lp-fin-range:focus-visible { outline: 2px solid var(--accent, #4c7dff); outline-offset: 1px; }
.lp-fin-metrics { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); border-top: 1px solid var(--wv-hairline); }
.lp-fin-metric { min-width: 0; padding: 10px 12px 9px 0; border-bottom: 1px solid var(--wv-hairline); display: flex; flex-direction: column; gap: 3px; }
.lp-fin-metric:nth-child(odd) { margin-right: 14px; }
.lp-fin-key { color: var(--text-secondary); font-size: 12.5px; line-height: 1.3; }
.lp-fin-value { color: var(--text-primary); font-size: var(--wv-answer-data-size); line-height: 1.3; font-weight: 600; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.lp-chart-pill { white-space: nowrap; }
.lp-fin-driver-cite { margin-left: .28em; }
@media (min-width: 768px) {
  .lp-scroll { padding-left: 32px; padding-right: 32px; }
  .lp-answer-lead { max-width: 72ch; }
}
@media (max-width: 480px) {
  .lp-rich-finance { padding: 14px 14px 15px; }
  .lp-fin-ranges { width: calc(100% + 28px); margin-left: -14px; margin-right: -14px; padding-left: 14px; padding-right: 14px; }
  .lp-fin-metrics { grid-template-columns: 1fr; }
  .lp-fin-metric:nth-child(odd) { margin-right: 0; }
}

/* A baseball line score has 13 columns. Percentage heuristics make those widths sum beyond 100%
   and crush Team into inning 2. Give the identity column a real width and scroll only on phones. */
.lp-table-linescore-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: thin; }
.lp-table-linescore { min-width: 650px; table-layout: fixed; }
.lp-table-linescore col.lp-linescore-teamcol { width: 132px; }
.lp-table-linescore th, .lp-table-linescore td { padding-left: 6px; padding-right: 6px; white-space: nowrap; }
.lp-table-linescore th.lp-linescore-team, .lp-table-linescore td.lp-linescore-team { padding-left: 2px; padding-right: 12px; overflow: hidden; text-overflow: ellipsis; }
.lp-table-linescore th.lp-td-num, .lp-table-linescore td.lp-td-num { text-align: left; font-variant-numeric: tabular-nums; }

/* ── Actionable close chips (reminder / price alert / where to watch) ── */
.lp-actionchips { display: flex; flex-wrap: wrap; gap: 8px; margin: 10px 0 2px 12px; }
.lp-actionchip {
  border: 1px solid var(--wv-hairline); background: var(--wv-panel-tint); border-radius: 999px;
  padding: 7px 13px; font-size: 13px; font-weight: 600; color: var(--text-primary);
  cursor: pointer; font-family: inherit; transition: background var(--transition-fast);
}
.lp-actionchip:hover { background: var(--wv-hl-tint); }
.lp-actionchip:active { transform: scale(0.97); }

/* ── Semantic answer composition ────────────────────────────────────────────
   The adapter labels each block's role. Rows own external rhythm; prose/table/list children own
   only their internal layout, so model block boundaries cannot make one answer look assembled. */
.lp-answer-lead { font-size: var(--wv-answer-lead-size); line-height: 25px; letter-spacing: -0.012em; color: var(--text-primary); }
.lp-answer-row-lead + .lp-answer-row-data { margin-top: var(--wv-answer-block-gap); }
.lp-row.waivy.lp-answer-row-support { margin-top: var(--wv-answer-block-gap); }
.lp-row.waivy.lp-answer-row-aside { margin-top: var(--wv-answer-block-gap); }
.lp-row.waivy.lp-answer-row-section,
.lp-row.waivy.lp-answer-row-data { margin-top: var(--wv-answer-section-gap); }
.lp-row.waivy.lp-answer-row-close { margin-top: var(--wv-answer-block-gap); }
.lp-row.waivy.lp-answer-row-section + .lp-row.waivy.lp-answer-row-data,
.lp-row.waivy:has(.lp-h2, .lp-h3) + .lp-row.waivy.lp-answer-row-data { margin-top: var(--wv-answer-heading-content-gap); }
.lp-answer-row-support:has(.lp-aside:last-child) + .lp-answer-row-section { margin-top: 0; }
.lp-vault-body[hidden] { display: none; }

/* ── AI Mode compare pane (built by waivy-adapter.js cmp*) ─────────────
   Side pane for the waivy-vs-Google-AI-Mode live compare. Fixed right
   panel below the header on desktop, bottom sheet on mobile. z-index 40:
   above the thread, below the place sheet (60) and header stays clear
   because the pane starts at --hdr-clearance. */
.lp-model-toggle {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 32px; padding: 5px 9px 5px 6px;
  border: 1px solid var(--border-color); border-radius: 999px;
  background: var(--bg-app); color: var(--text-primary);
  font: 600 0.78rem/1 var(--font-system); cursor: pointer; white-space: nowrap;
  transition: background var(--transition-fast), border-color var(--transition-fast), transform var(--transition-fast);
}
.lp-model-toggle:hover { background: var(--wv-chip-tint); }
.lp-model-toggle:active { transform: scale(0.97); }
.lp-model-mark {
  display: inline-grid; place-items: center; width: 20px; height: 20px; border-radius: 50%;
  background: var(--text-primary); color: var(--text-inverse); font-size: 0.68rem; font-weight: 700;
}
.lp-model-toggle[data-profile="deepseek"] .lp-model-mark { background: #315fdb; color: #fff; }
.lp-model-swap { color: var(--text-tertiary); font-size: 0.72rem; }
.lp-model-toggle.is-unavailable { animation: lp-model-nudge 320ms ease; }
@keyframes lp-model-nudge { 33% { transform: translateX(-3px); } 66% { transform: translateX(3px); } }

/* Collapsed raw provider output shown after each experimental answer. */
.lp-model-lab {
  width: min(100%, 760px); margin: 2px 0 0; border: 1px solid var(--wv-hairline);
  border-radius: 12px; background: var(--wv-panel-tint); color: var(--text-primary); overflow: hidden;
}
.lp-model-lab > summary {
  display: flex; align-items: center; gap: 10px; padding: 9px 12px; cursor: pointer;
  list-style: none; user-select: none; font-size: 0.76rem;
}
.lp-model-lab > summary::-webkit-details-marker { display: none; }
.lp-model-lab > summary::before { content: "›"; color: var(--text-tertiary); font-size: 1rem; transform-origin: center; transition: transform var(--transition-fast); }
.lp-model-lab[open] > summary::before { transform: rotate(90deg); }
.lp-model-lab-title { font-weight: 700; }
.lp-model-lab-meta { margin-left: auto; color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.lp-model-lab-head {
  display: flex; flex-wrap: wrap; gap: 6px 14px; padding: 8px 12px;
  border-top: 1px solid var(--wv-hairline); color: var(--text-secondary); font-size: 0.72rem;
}
.lp-model-call { padding: 10px 12px; border-top: 1px solid var(--wv-hairline); }
.lp-model-call-meta { display: flex; flex-wrap: wrap; gap: 5px 12px; margin-bottom: 7px; color: var(--text-secondary); font-size: 0.7rem; }
.lp-model-call-meta b { color: var(--text-primary); }
.lp-model-call pre {
  max-height: 320px; margin: 0; padding: 10px; overflow: auto; border-radius: 8px;
  background: color-mix(in srgb, var(--bg-app) 72%, transparent); color: var(--text-primary);
  font: 0.68rem/1.5 "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  white-space: pre-wrap; overflow-wrap: anywhere; tab-size: 2;
}
.lp-model-lab-empty { padding: 12px; border-top: 1px solid var(--wv-hairline); color: var(--text-secondary); font-size: 0.76rem; }

.lp-cmp-toggle {
  display: inline-flex; align-items: center; gap: 7px;
  font-family: var(--font-system); font-size: 0.86rem; font-weight: 600;
  color: var(--text-primary); background: var(--imsg-bubble-grey);
  border: 1px solid var(--border-color); border-radius: 999px;
  padding: 7px 13px; cursor: pointer; white-space: nowrap;
  transition: background var(--transition-fast), border-color var(--transition-fast), color var(--transition-fast);
}
.lp-cmp-toggle:hover { background: var(--wv-chip-tint); }
.lp-cmp-toggle[aria-pressed="true"] { background: var(--text-primary); color: var(--text-inverse); border-color: var(--text-primary); }
.lp-cmp-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--text-tertiary); flex: none; transition: background var(--transition-fast); }
.lp-cmp-dot.is-warming { background: #c48a1b; animation: lp-cmp-pulse 1.2s ease-in-out infinite; }
.lp-cmp-dot.is-warm { background: var(--wv-up); }
@keyframes lp-cmp-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }

.lp-cmp-pane {
  position: fixed; top: var(--hdr-clearance); right: 0; bottom: 0; z-index: 40;
  width: 480px; max-width: 50vw;
  display: flex; flex-direction: column;
  background: var(--bg-app); border-left: 1px solid var(--border-color);
  box-shadow: -12px 0 32px rgba(31, 33, 38, 0.08);
  font-family: var(--font-system); color: var(--text-primary);
}
.lp-cmp-pane[hidden] { display: none; }
.lp-cmp-head { display: flex; align-items: center; gap: 10px; padding: 12px 16px; border-bottom: 1px solid var(--border-color); }
.lp-cmp-title { font-weight: 700; font-size: 0.92rem; }
.lp-cmp-warm { display: inline-flex; align-items: center; gap: 6px; margin-left: auto; font-size: 0.74rem; color: var(--text-secondary); }
.lp-cmp-close { border: none; background: none; color: var(--text-tertiary); font-size: 0.9rem; cursor: pointer; padding: 4px; }
.lp-cmp-close:hover { color: var(--text-primary); }
.lp-cmp-body { flex: 1; overflow-y: auto; padding: 16px; font-size: 0.88rem; line-height: 1.55; }
.lp-cmp-body h3, .lp-cmp-body h4, .lp-cmp-body h5, .lp-cmp-body h6 { margin: 14px 0 6px; font-size: 0.95rem; }
.lp-cmp-body p { margin: 0 0 10px; }
.lp-cmp-body ul { margin: 0 0 10px; padding-left: 20px; }
.lp-cmp-body li { margin: 3px 0; }
.lp-cmp-body a { color: var(--wv-accent); text-decoration: none; border-bottom: 1px solid var(--wv-link-underline); }
.lp-cmp-body table { width: 100%; border-collapse: collapse; font-size: 0.82rem; margin: 0 0 10px; }
.lp-cmp-body th, .lp-cmp-body td { text-align: left; padding: 5px 8px; border-bottom: 1px solid var(--border-color); }
.lp-cmp-body th { color: var(--text-secondary); font-weight: 600; }
.lp-cmp-state { color: var(--text-secondary); padding: 12px 2px; }
.lp-cmp-not-shown {
  display: flex; flex-direction: column; gap: 3px; padding: 12px;
  border: 1px solid var(--border-color); border-radius: 10px; background: var(--wv-panel-tint);
}
.lp-cmp-not-shown b { color: var(--text-primary); }
.lp-cmp-sources { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--border-color); }
.lp-cmp-sources h3 { margin: 0 0 8px; color: var(--text-primary); }
.lp-cmp-sources ul { margin: 0; padding: 0; list-style: none; }
.lp-cmp-sources li { display: flex; flex-direction: column; gap: 1px; padding: 7px 0; }
.lp-cmp-sources li + li { border-top: 1px solid var(--border-color); }
.lp-cmp-sources li span { color: var(--text-secondary); font-size: 0.8rem; }
.lp-cmp-note { margin-top: 8px; font-size: 0.78rem; color: #c48a1b; }
.lp-cmp-spinner { display: inline-block; width: 12px; height: 12px; margin-right: 8px; border: 2px solid var(--border-color); border-top-color: var(--text-secondary); border-radius: 50%; animation: lp-cmp-spin 0.8s linear infinite; vertical-align: -2px; }
@keyframes lp-cmp-spin { to { transform: rotate(360deg); } }
.lp-cmp-foot { padding: 10px 16px; border-top: 1px solid var(--border-color); font-size: 0.72rem; color: var(--text-tertiary); }
.lp-cmp-foot:empty { display: none; }
@media (max-width: 700px) {
  .lp-model-label, .lp-model-swap { display: none; }
  .lp-model-toggle { padding: 5px; }
  .lp-model-lab > summary { align-items: flex-start; flex-wrap: wrap; }
  .lp-model-lab-meta { width: calc(100% - 26px); margin-left: 26px; }
  .lp-cmp-pane {
    top: auto; bottom: 0; left: 0; width: 100%; max-width: none; height: 62dvh;
    border-left: none; border-top: 1px solid var(--border-color);
    border-radius: 16px 16px 0 0; box-shadow: 0 -12px 32px rgba(31, 33, 38, 0.12);
  }
  .lp-cmp-toggle { padding: 6px 9px; font-size: 0.78rem; }
}
