
/* ── Page shell ─────────────────────────────────────── */
body {
  background: var(--bg);
}

/* Author-card names are <h2> for document outline / SEO; reset the UA heading
   box model so the heading element does not alter the card layout (the per-card
   font-size/weight/colour rules further below still control their appearance). */
.card-band-name,
.card-stripe-name,
.card-split-name,
.card-numeral-name,
.card-stamp-name,
.card-compact-name {
  margin: 0;
  font-size: inherit;
  font-weight: inherit;
}

/* Home reuses the shared siteNav() (brand mark + wordmark + search) so global
   navigation is identical across home/author/post. The home header just widens
   the nav to the mosaic's 1280px gutter and adds the tagline + rule beneath. */
.site-header {
  position: relative;
  z-index: 10;
}
.site-header .site-nav {
  max-width: 1280px;
  padding: 2.5rem 3rem 0;
  align-items: center;
}
.site-header .site-nav-wordmark {
  font-size: clamp(1.4rem, 3vw, 1.9rem);
}
.site-header .site-nav-brand .brand-mark {
  width: 32px;
  height: 32px;
}
.site-tagline {
  max-width: 1280px;
  margin: 0.55rem auto 0;
  padding: 0 3rem;
  font-size: 0.72rem;
  color: var(--ink-muted);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 500;
}
.site-rule {
  border: none;
  border-top: 1px solid var(--border-gold);
  max-width: 1280px;
  margin: 0 3rem;
}

/* ── Hero band ──────────────────────────────────────── */
/* A visible first-impression band above the mosaic: oversized Cormorant
   wordmark (the page's real, visible H1), a short tagline, and a champagne-gold
   accent rule — scaled to read with the same weight as the author page's
   author-hero so the home page no longer leads with an sr-only-only title. */
.site-hero {
  max-width: 1280px;
  margin: 2.75rem auto 0;
  padding: 0 3rem;
  animation: fadeDown 0.45s 0.06s var(--ease-out-expo) both;
}
.site-hero-eyebrow {
  display: block;
  font-size: 0.72rem;
  color: var(--ink-muted);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-weight: 600;
  margin-bottom: 0.6rem;
}
.site-hero-title {
  font-family: 'Cormorant Garamond', serif;
  font-size: clamp(2.6rem, 6vw, 4.4rem);
  font-weight: 700;
  line-height: 1.02;
  letter-spacing: 0.01em;
  color: var(--ink);
  margin: 0;
  text-wrap: balance;
}
.site-hero-tagline {
  margin: 0.85rem 0 0;
  max-width: 46ch;
  font-size: clamp(0.92rem, 1.6vw, 1.05rem);
  line-height: 1.6;
  color: var(--ink-muted);
}
.site-hero-rule {
  border: none;
  border-top: 2px solid var(--gold);
  width: 64px;
  margin: 1.4rem 0 0;
  opacity: 0.85;
}

/* ── Grid ───────────────────────────────────────────── */
/* A 12-column grid with DENSE auto-placement: cards declare only how many
   columns they span (never a fixed row), and the browser tiles them into a
   repeatable rhythm. This keeps the deliberate asymmetric mosaic for the first
   six authors yet degrades gracefully — a 7th, 8th… author simply continues the
   same cadence instead of orphaning a card. The span pattern repeats every 6
   cards (matching the six card variants) via the .span-* classes below. */
.authors-grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  grid-auto-flow: row dense;
  gap: 1.25rem;
  max-width: 1280px;
  margin: 1.75rem auto 4rem;
  padding: 0 3rem;
}

/* Column spans drive the mosaic. The repeating rhythm per 6-card block is
   7+5 / 4+4+4 / 6(+6) which sums to 12 per row and tiles cleanly for any N. */
.card.span-7 { grid-column: span 7; }
.card.span-6 { grid-column: span 6; }
.card.span-5 { grid-column: span 5; }
.card.span-4 { grid-column: span 4; }

/* ── Base card ──────────────────────────────────────── */
.card {
  background: oklch(99% 0.005 75);
  border: 1px solid var(--border);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  transition: transform 0.22s var(--ease-out-expo), box-shadow 0.22s var(--ease-out-expo);
}
@media (prefers-color-scheme: dark) {
  .card { background: oklch(16% 0.015 62); }
}
.card:hover {
  transform: translateY(-3px);
  box-shadow: 0 12px 40px color-mix(in oklch, var(--c-accent) 18%, transparent);
}

/* ── Shared structural template across ALL variants ──────
   The six cards are intentionally distinct in COLOR/accent treatment, but they
   must read as one family: same header height rhythm, same initial size, same
   post-list padding. These shared rules pin that structure so only the accent
   treatment (fill / stripe / clip / ghost / footer / tint) varies per variant.
   --card-pad : the single horizontal/footer padding used by every header + list
   --card-initial : the circular/lettered initial diameter (where bounded) */
.card {
  --card-pad: 1.25rem;
  --card-initial: 46px;
}
/* Every header shares one vertical rhythm so the cards line up as a system. */
.card--banner .card-hero-band,
.card--stripe .card-stripe-header,
.card--split .card-split-header,
.card--numeral .card-numeral-header,
.card--stamp .card-stamp-footer,
.card--compact .card-compact-header {
  padding-left: var(--card-pad);
  padding-right: var(--card-pad);
}
/* Bounded (circular) initials share one diameter; the two unbounded display
   initials (banner band + split overlay) keep their oversized type as the one
   permitted per-variant flourish. */
.card--stripe .card-stripe-initial,
.card--stamp .card-stamp-initial,
.card--compact .card-compact-initial {
  width: var(--card-initial);
  height: var(--card-initial);
  font-size: 1.4rem;
}

/* Shared post list styles across all card variants */
.card-posts {
  padding: 0.9rem var(--card-pad) 1.1rem;
  display: flex;
  flex-direction: column;
  gap: 0;
  flex: 1;
}
.card-post-link {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.75rem;
  padding: 0.45rem 0;
  border-bottom: 1px solid var(--border);
  text-decoration: none;
}
.card-post-link:last-child {
  border-bottom: none;
}
.card-post-title {
  font-size: 0.875rem;
  color: var(--ink);
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  transition: color 0.18s var(--ease-out-quart);
}
.card-post-link:hover .card-post-title {
  color: var(--c-accent-text);
}
.card-post-date {
  font-size: 0.72rem;
  color: var(--ink-muted);
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
}
.card-empty {
  font-size: 0.85rem;
  color: var(--ink-muted);
  padding: 0.5rem 0;
  font-style: italic;
}

/* ── Card 0: Banner (朱奕樟 · champagne gold) ─────── */
.card--banner .card-hero-band {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  padding: 2rem var(--card-pad) 1.75rem;
  background: var(--c-accent);
  text-decoration: none;
  transition: filter 0.2s var(--ease-out-quart);
}
.card--banner .card-hero-band:hover {
  filter: brightness(1.08);
}
.card--banner .card-band-initial {
  font-family: 'Cormorant Garamond', serif;
  font-size: 4rem;
  font-weight: 700;
  color: oklch(from var(--c-accent) calc(l + 0.55) c h);
  line-height: 1;
  opacity: 0.92;
}
.card--banner .card-band-meta {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}
.card--banner .card-band-name {
  font-family: 'Cormorant Garamond', serif;
  font-size: 2rem;
  font-weight: 700;
  color: var(--c-on-accent);
  letter-spacing: 0.03em;
  line-height: 1;
}
.card--banner .card-band-count {
  font-size: 0.78rem;
  color: oklch(95% 0.02 78 / 0.92);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-weight: 500;
}

/* ── Card 1: Stripe (张建宇 · forest green) ─────── */
.card--stripe {
  flex-direction: row;
  align-items: stretch;
}
.card--stripe .card-stripe-bar {
  width: 6px;
  background: var(--c-accent);
  flex-shrink: 0;
}
.card--stripe .card-stripe-body {
  display: flex;
  flex-direction: column;
  flex: 1;
  overflow: hidden;
}
.card--stripe .card-stripe-header {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 1.25rem var(--card-pad) 1rem;
  background: var(--c-tint);
  text-decoration: none;
  transition: background 0.18s var(--ease-out-quart);
}
@media (prefers-color-scheme: dark) {
  .card--stripe .card-stripe-header {
    background: color-mix(in oklch, var(--c-accent) 14%, oklch(17% 0.018 62));
  }
}
.card--stripe .card-stripe-header:hover {
  background: color-mix(in oklch, var(--c-accent) 22%, var(--bg));
}
.card--stripe .card-stripe-initial {
  border-radius: 50%;
  background: var(--c-accent);
  color: var(--c-on-accent);
  font-family: 'Cormorant Garamond', serif;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.card--stripe .card-stripe-name {
  font-family: 'Cormorant Garamond', serif;
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--ink);
  line-height: 1.2;
}
.card--stripe .card-stripe-count {
  font-size: 0.78rem;
  color: var(--c-accent-text);
  margin-top: 0.2rem;
  letter-spacing: 0.04em;
  font-weight: 500;
}
.card--stripe .card-posts {
  padding: 0.9rem var(--card-pad) 1rem;
}

/* ── Card 2: Split (齐钒羽 · cobalt blue) ─────── */
.card--split .card-split-header {
  position: relative;
  display: block;
  text-decoration: none;
  overflow: hidden;
}
.card--split .card-split-bg {
  height: 90px;
  background: var(--c-accent);
  clip-path: polygon(0 0, 100% 0, 100% 65%, 0 100%);
  transition: filter 0.2s var(--ease-out-quart);
}
.card--split .card-split-header:hover .card-split-bg {
  filter: brightness(1.1);
}
.card--split .card-split-content {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  padding: 1rem var(--card-pad);
}
.card--split .card-split-initial {
  font-family: 'Cormorant Garamond', serif;
  font-size: 2.5rem;
  font-weight: 700;
  color: var(--c-on-accent);
  line-height: 1;
  flex-shrink: 0;
}
.card--split .card-split-info {
  padding-top: 0.2rem;
}
.card--split .card-split-name {
  font-family: 'Cormorant Garamond', serif;
  font-size: 1.3rem;
  font-weight: 700;
  color: var(--c-on-accent);
  line-height: 1.2;
}
.card--split .card-split-count {
  font-size: 0.78rem;
  color: oklch(97% 0.008 78 / 0.95);
  margin-top: 0.2rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 500;
}
.card--split .card-posts {
  margin-top: 0.25rem;
  padding: 0.5rem var(--card-pad) 1rem;
}

/* ── Card 3: Numeral (高鹏 · teal) ─────────────── */
.card--numeral .card-numeral-header {
  display: flex;
  align-items: center;
  padding: 1.1rem var(--card-pad) 0.8rem;
  border-bottom: 2px solid var(--c-accent);
  text-decoration: none;
  position: relative;
  overflow: hidden;
  gap: 0.75rem;
  transition: background 0.18s var(--ease-out-quart);
}
.card--numeral .card-numeral-header:hover {
  background: var(--c-tint);
}
@media (prefers-color-scheme: dark) {
  .card--numeral .card-numeral-header:hover {
    background: color-mix(in oklch, var(--c-accent) 14%, oklch(16% 0.015 62));
  }
}
.card--numeral .card-numeral-ghost {
  font-family: 'Cormorant Garamond', serif;
  font-size: 4.5rem;
  font-weight: 700;
  color: var(--c-accent);
  opacity: 0.12;
  line-height: 1;
  position: absolute;
  right: 0.5rem;
  top: 50%;
  transform: translateY(-50%);
  pointer-events: none;
  user-select: none;
}
.card--numeral .card-numeral-name {
  font-family: 'Cormorant Garamond', serif;
  font-size: 1.3rem;
  font-weight: 700;
  color: var(--ink);
  line-height: 1.2;
}
.card--numeral .card-numeral-count {
  font-size: 0.78rem;
  color: var(--c-accent-text);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  margin-top: 0.2rem;
  font-weight: 600;
}
.card--numeral .card-posts {
  padding: 0.75rem var(--card-pad) 1rem;
}

/* ── Card 4: Stamp (冯建设 · crimson) ────────── */
.card--stamp {
  flex-direction: column;
  justify-content: space-between;
}
.card--stamp .card-stamp-posts {
  padding: 1.1rem var(--card-pad) 0.75rem;
  flex: 1;
  display: flex;
  flex-direction: column;
}
.card--stamp .card-post-link {
  flex: none;
}
.card--stamp .card-stamp-footer {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 1rem var(--card-pad);
  background: var(--c-accent);
  text-decoration: none;
  transition: filter 0.2s var(--ease-out-quart);
}
.card--stamp .card-stamp-footer:hover {
  filter: brightness(1.1);
}
.card--stamp .card-stamp-initial {
  border-radius: 50%;
  background: oklch(from var(--c-accent) calc(l + 0.52) c h / 0.22);
  border: 1.5px solid oklch(97% 0.01 78 / 0.5);
  color: var(--c-on-accent);
  font-family: 'Cormorant Garamond', serif;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.card--stamp .card-stamp-name {
  font-family: 'Cormorant Garamond', serif;
  font-size: 1.2rem;
  font-weight: 700;
  color: var(--c-on-accent);
  line-height: 1.2;
}
.card--stamp .card-stamp-count {
  font-size: 0.78rem;
  color: oklch(97% 0.008 78 / 0.95);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  margin-top: 0.15rem;
  font-weight: 500;
}

/* ── Card 5+: Compact (陈思慧 etc.) ─────────────── */
.card--compact .card-compact-header {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 1.1rem var(--card-pad) 0.9rem;
  background: var(--c-tint);
  text-decoration: none;
  transition: background 0.18s var(--ease-out-quart);
}
@media (prefers-color-scheme: dark) {
  .card--compact .card-compact-header {
    background: color-mix(in oklch, var(--c-accent) 14%, oklch(17% 0.018 62));
  }
}
.card--compact .card-compact-header:hover {
  background: color-mix(in oklch, var(--c-accent) 22%, var(--bg));
}
.card--compact .card-compact-initial {
  border-radius: 50%;
  background: var(--c-accent);
  color: var(--c-on-accent);
  font-family: 'Cormorant Garamond', serif;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.card--compact .card-compact-name {
  font-family: 'Cormorant Garamond', serif;
  font-size: 1.2rem;
  font-weight: 700;
  color: var(--ink);
  line-height: 1.2;
}
.card--compact .card-compact-count {
  font-size: 0.78rem;
  color: var(--c-accent-text);
  margin-top: 0.2rem;
  letter-spacing: 0.04em;
  font-weight: 500;
}

/* ── Entrance animation ─────────────────────────── */
@keyframes fadeSlideUp {
  from {
    opacity: 0;
    transform: translateY(18px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
.card {
  animation: fadeSlideUp 0.55s var(--ease-out-expo) both;
  /* Capped stagger: each card carries its zero-based index in --i (set inline).
     The delay grows 0.06s per card but clamps at the 8th, so a 9th, 20th… author
     still animates in (no pop-in) without an ever-growing wait for large rosters.
     calc(min()) is widely supported; --i falls back to 0 if absent. */
  animation-delay: calc(min(var(--i, 0), 8) * 0.06s + 0.08s);
}

@keyframes fadeDown {
  from { opacity: 0; transform: translateY(-8px); }
  to   { opacity: 1; transform: translateY(0); }
}
.site-header {
  animation: fadeDown 0.4s var(--ease-out-expo) both;
}

/* ── Footer ─────────────────────────────────────── */
.site-footer {
  max-width: 1280px;
  margin: 0 auto;
  padding: 1.75rem 3rem;
  border-top: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.site-footer-text {
  font-size: 0.72rem;
  color: var(--ink-muted);
  letter-spacing: 0.06em;
}

/* Search markup/CSS/JS is the shared siteNav() component (SITE_NAV_CSS /
   SITE_NAV_JS); the home page no longer defines its own copy, so the box is
   pixel-identical to author/post pages. */

/* ── Responsive ─────────────────────────────────── */
/* Collapse the 12-col mosaic to a tidy 6-col rhythm: the wide banner spans the
   full row, every other variant becomes a half (3 of 6). Dense auto-flow tiles
   them two-per-row regardless of author count. */
@media (max-width: 1100px) {
  .authors-grid {
    grid-template-columns: repeat(6, 1fr);
    padding: 0 2rem;
  }
  .card.span-7 { grid-column: span 6; }
  .card.span-6,
  .card.span-5,
  .card.span-4 { grid-column: span 3; }
  .site-header .site-nav { padding: 2rem 2rem 0; }
  .site-tagline { padding: 0 2rem; }
  .site-rule { margin: 0 2rem; }
  .site-hero { padding: 0 2rem; }
  .site-footer { padding: 1.5rem 2rem; }
}
@media (max-width: 680px) {
  .site-header .site-nav { padding: 1.5rem 1.25rem 0; }
  .site-tagline { padding: 0 1.25rem; }
  .site-hero { padding: 0 1.25rem; margin-top: 2rem; }
  .authors-grid {
    grid-template-columns: 1fr;
    padding: 0 1.25rem;
    gap: 1rem;
  }
  .card.span-7,
  .card.span-6,
  .card.span-5,
  .card.span-4 { grid-column: 1 / -1; }
  .site-rule { margin: 0 1.25rem; }
  .site-footer { padding: 1.25rem; }
}


.site-nav {
  max-width: 760px;
  margin: 0 auto;
  padding: 1.1rem 2.5rem 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}
.site-nav-brand {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  text-decoration: none;
}
.site-nav-brand .brand-mark {
  display: block;
  flex-shrink: 0;
  transition: transform 0.2s var(--ease-out-quart);
}
.site-nav-brand:hover .brand-mark { transform: rotate(-4deg) scale(1.05); }
.site-nav-wordmark {
  font-family: 'Cormorant Garamond', serif;
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--gold);
  letter-spacing: 0.02em;
}
/* Current-page (home) wayfinding: the brand acts as the active "Home" nav item,
   underlined with the accent so users see where they are. On author/post pages
   the brand stays a plain link back home. */
.site-nav-brand--active .site-nav-wordmark {
  border-bottom: 2px solid var(--gold);
  padding-bottom: 1px;
}
.site-nav-search {
  position: relative;
  width: 220px;
}
.site-nav-search input {
  width: 100%;
  padding: 0.45rem 0.9rem 0.45rem 2.1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  font-size: 0.8rem;
  background: var(--bg);
  color: var(--ink);
  outline: none;
  transition: border-color 0.18s, box-shadow 0.18s;
}
.site-nav-search input:focus {
  border-color: var(--gold);
  box-shadow: 0 0 0 3px color-mix(in oklch, var(--gold) 15%, transparent);
}
.site-nav-search-icon {
  position: absolute;
  left: 10px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--ink-muted);
  font-size: 0.8rem;
  pointer-events: none;
}
.site-nav .search-results {
  display: none;
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: 0 8px 32px oklch(0% 0 0 / 0.12);
  max-height: 360px;
  overflow-y: auto;
  z-index: 100;
}
.site-nav .search-results.open { display: block; }
.site-nav .search-result-item {
  display: block;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
  text-decoration: none;
  transition: background 0.12s;
}
.site-nav .search-result-item:last-child { border-bottom: none; }
.site-nav .search-result-item:hover,
.site-nav .search-result-item.active { background: var(--bg-subtle); }
.site-nav .search-result-item.active { outline: 2px solid var(--gold); outline-offset: -2px; }
.site-nav .search-status,
.site-nav .search-count {
  padding: 8px 14px;
  font-size: 0.72rem;
  color: var(--ink-muted);
  letter-spacing: 0.04em;
  border-bottom: 1px solid var(--border);
}
.site-nav .search-result-title { font-size: 0.88rem; font-weight: 600; color: var(--ink); margin-bottom: 2px; }
.site-nav .search-result-meta { font-size: 0.72rem; color: var(--ink-muted); }
.site-nav .search-result-snippet { font-size: 0.78rem; color: var(--ink-muted); margin-top: 3px; line-height: 1.4; }
.site-nav .search-empty { padding: 16px; text-align: center; font-size: 0.85rem; color: var(--ink-muted); }
@media (max-width: 680px) {
  .site-nav { flex-wrap: wrap; padding: 1rem 1.25rem 0; }
  .site-nav-search { width: 100%; }
  .site-nav-search input { font-size: 16px; }
}


/* ── AI Chat Widget ─────────────────────────── */
.ai-chat-fab {
  position: fixed;
  right: 20px;
  bottom: 20px;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: var(--gold);
  color: var(--on-accent);
  border: none;
  cursor: pointer;
  font-size: 20px;
  box-shadow: 0 4px 16px oklch(0% 0 0 / 0.15);
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform 0.2s, box-shadow 0.2s;
}
.ai-chat-fab:hover {
  transform: scale(1.08);
  box-shadow: 0 6px 24px oklch(0% 0 0 / 0.22);
}
/* Calm reading: on long posts the FAB stays hidden until the reader has scrolled
   into the article, then fades in. JS adds .revealed; without JS it falls back to
   always-visible (the rule below only hides while the gated flag is set). Reveal
   is a gentle fade so it never competes with the prose on first paint. */
.ai-chat-fab.gated {
  opacity: 0;
  transform: translateY(12px) scale(0.9);
  pointer-events: none;
  transition: opacity 0.3s var(--ease-out-quart), transform 0.3s var(--ease-out-quart);
}
.ai-chat-fab.gated.revealed {
  opacity: 1;
  transform: translateY(0) scale(1);
  pointer-events: auto;
}
@media (prefers-reduced-motion: reduce) {
  .ai-chat-fab.gated { transition: opacity 0.3s linear; transform: none; }
  .ai-chat-fab.gated.revealed { transform: none; }
}
.ai-chat-panel {
  display: none;
  position: fixed;
  right: 20px;
  bottom: 80px;
  width: 360px;
  max-height: 480px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 12px 48px oklch(0% 0 0 / 0.15);
  z-index: 1000;
  flex-direction: column;
  overflow: hidden;
}
.ai-chat-panel.open { display: flex; }
.ai-chat-panel.expanded {
  width: min(640px, calc(100vw - 40px));
  max-height: min(720px, calc(100vh - 100px));
  bottom: 20px;
}
.ai-chat-header {
  padding: 10px 14px;
  background: var(--gold);
  color: var(--on-accent);
  font-size: 0.82rem;
  font-weight: 600;
  display: flex;
  align-items: center;
  gap: 6px;
}
.ai-chat-header span { flex: 1; }
.ai-chat-header button {
  background: none;
  border: none;
  color: var(--on-accent);
  opacity: 0.8;
  font-size: 15px;
  cursor: pointer;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  border-radius: 4px;
  transition: background 0.15s, color 0.15s;
}
.ai-chat-header button:hover {
  /* A dark scrim instead of a white wash so the hover state keeps adequate
     contrast on light/champagne accents (white-on-light washed out before). */
  background: oklch(0% 0 0 / 0.18);
  color: var(--on-accent);
  opacity: 1;
}
/* Header buttons sit on the accent fill, where the page-wide gold focus outline
   has poor contrast. Use the on-accent color for a 2px outline so keyboard focus
   is clearly visible on both light and dark accents. */
.ai-chat-header button:focus-visible {
  outline: 2px solid var(--on-accent);
  outline-offset: 2px;
  opacity: 1;
}
.ai-chat-messages {
  flex: 1;
  overflow-y: auto;
  padding: 12px 16px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-height: 200px;
}
.ai-msg {
  padding: 8px 12px;
  border-radius: 8px;
  font-size: 0.85rem;
  line-height: 1.55;
  max-width: 90%;
  word-break: break-word;
}
.ai-msg.user {
  background: var(--gold-tint);
  color: var(--ink);
  align-self: flex-end;
  border-bottom-right-radius: 2px;
}
.ai-msg.bot {
  background: var(--bg-subtle);
  color: var(--ink);
  align-self: flex-start;
  border-bottom-left-radius: 2px;
}
.ai-msg.bot.loading::after {
  content: '...';
  animation: dotPulse 1s infinite;
}
@keyframes dotPulse {
  0%,80%,100% { opacity: 0.3; }
  40% { opacity: 1; }
}
.ai-msg.bot p { margin: 0 0 0.5em; }
.ai-msg.bot p:last-child { margin: 0; }
.ai-msg.bot code {
  background: oklch(0% 0 0 / 0.06);
  padding: 1px 4px;
  border-radius: 3px;
  font-size: 0.82em;
}
.ai-msg.bot pre {
  background: oklch(0% 0 0 / 0.05);
  padding: 8px 10px;
  border-radius: 4px;
  overflow-x: auto;
  margin: 0.4em 0;
  font-size: 0.8em;
}
.ai-msg.bot pre code { background: none; padding: 0; }
.ai-msg.bot ul, .ai-msg.bot ol { padding-left: 1.2em; margin: 0.3em 0; }
.ai-msg.bot strong { font-weight: 600; }
.ai-msg.bot h1,.ai-msg.bot h2,.ai-msg.bot h3,.ai-msg.bot h4 {
  font-size: 0.9rem;
  font-weight: 600;
  margin: 0.5em 0 0.2em;
}
.ai-msg.bot blockquote {
  border-left: 2px solid var(--gold);
  padding-left: 8px;
  margin: 0.3em 0;
  color: var(--ink-muted);
}
.ai-chat-input {
  display: flex;
  gap: 8px;
  padding: 10px 12px;
  border-top: 1px solid var(--border);
}
.ai-chat-input input {
  flex: 1;
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px 12px;
  font-size: 0.85rem;
  background: var(--bg);
  color: var(--ink);
  outline: none;
}
.ai-chat-input input:focus { border-color: var(--gold); }
.ai-chat-input button {
  background: var(--gold);
  color: var(--on-accent);
  border: none;
  border-radius: 6px;
  padding: 8px 14px;
  font-size: 0.85rem;
  cursor: pointer;
  white-space: nowrap;
  font-weight: 500;
}
.ai-chat-input button:disabled { opacity: 0.5; cursor: not-allowed; }
/* Lock background scroll while the chat dialog is open so iOS Safari does not
   scroll the page behind the fixed panel (scroll-through). The fab/panel are
   position:fixed so they stay reachable; only the document body is frozen. */
body.ai-chat-lock { overflow: hidden; }
@media (max-width: 600px) {
  .ai-chat-panel { right: 8px; left: 8px; bottom: 72px; width: auto; max-height: 60vh; }
  .ai-chat-panel.expanded { bottom: 8px; max-height: calc(100vh - 16px); }
  .ai-chat-fab { right: 14px; bottom: 14px; width: 44px; height: 44px; }
  .ai-chat-header button { width: 32px; height: 32px; }
  /* 16px inputs avoid iOS Safari focus auto-zoom. */
  .ai-chat-input input { font-size: 16px; }
}
