/*!
 * Sterling SMB/Cherokee chat widget — Frederick & Sons "Sterling C" (Editorial) skin.
 *
 * WHAT THIS FILE IS: an EXTERNAL, palette-flipped reskin of the widget markup/JS in
 * /opt/cherokee/templates/_chat_widget.html (that file's <style> block, lines 202-917,
 * is the DARK original this file replaces — do not edit the dark <style> block, edit
 * this file and swap the <link> in). No markup or JS changes were made or are required;
 * every `.preacher-*` / `#preacher-*` selector from the original is reproduced here
 * 1:1 — only property VALUES (color/font/border/background/shadow) changed. Structural
 * properties (position/z-index/flex/transform/transition timing/@keyframes) are carried
 * over unchanged so the widget's open/close/expand/voice-mode mechanics keep working.
 *
 * REFERENCE (the look this mirrors): the canonical Sterling "Direction C — Editorial
 * Monolith" shipped estate-wide via /opt/preacher/fas-site/static/sterling/sterling.js
 * (its embedded `CSS` string) and demoed in /home/preacher/sterling-directions.html
 * (`.dirC` block). Paper panel, outlined-"LING" wordmark, left-rule bot messages,
 * ink user bubbles, mono chips. This file gets that same face onto the OLDER,
 * differently-marked-up SMB widget, which cannot be swapped for the sterling.js
 * web-component wholesale without a separate migration (different endpoint/auth/voice
 * wiring) — hence a parallel reskin rather than a re-point.
 *
 * EDITABILITY (owner ask, 2026-07-10): every color + font lives in the :root block
 * below as a CSS custom property. Changing the look later = editing these ~8 vars,
 * not hunting ~90 rules. Two exceptions, both deliberate, both commented at point of
 * use: (1) rgba() opacity variants of ink/lime are hardcoded numbers (e.g.
 * `rgba(10,10,10,.14)`) because CSS cannot interpolate a var()'s color channels into
 * an rgba() argument list without relative-color syntax (`rgb(from var(...) ...)`),
 * which is a browser-support risk not worth taking for an internal SMB tool — if you
 * change --strl-ink or --strl-lime, grep this file for their literal decimal triplets
 * (10,10,10 / 200,255,0) and update the opacity variants too; (2) `!important` is kept
 * ONLY on the exact properties the dark original marked `!important` — those exist to
 * defeat the estate's global `_brutal.css` reset (forces border-radius:0, strips
 * backgrounds site-wide) reaching into this widget's Shadow-DOM-less inline styles;
 * dropping them would silently regress the "see-through ghost bubble" bug that patch
 * already fixed once (see the D-launcher / brutalist-reconcile history below).
 *
 * DARK -> PAPER CONVERSION RULE (systematic, applied everywhere a translucent white/
 * near-black wash existed): every `rgba(255,255,255,X)` hairline/wash in the dark
 * source became `rgba(10,10,10,X)` at the SAME alpha (same relative tonal weight,
 * opposite base channel — a light-on-dark hairline becomes a dark-on-light hairline
 * of equal strength, not a guessed value). Lime (`#c8ff00` / `rgba(200,255,0,X)`)
 * opacity variants were left numerically unchanged — the accent is designed to read
 * atop varied surfaces and didn't need re-tuning for paper.
 *
 * CONSOLIDATION NOTE: the dark original accreted two dated `!important` patch blocks
 * appended at file-end ("Brutalist reconcile 2026-07-02" and the "D launcher" chat-
 * head-glyph patch) that override earlier, now-dead declarations for the same
 * selectors (e.g. #preacher-bubble was declared 3x: an original circular-avatar
 * button, then two override patches turning it into today's icon+label pill). This
 * file keeps ONE canonical rule per selector reflecting the CURRENTLY-EFFECTIVE
 * (post-cascade) shape, paper-flipped — not a replayed override stack. Also folded
 * three near-black shades the original used inconsistently (#040406, #0a0604 /
 * rgba(10,6,4,..), #0a0a0a) onto the single --strl-ink token.
 *
 * Fonts: Archivo (wordmark/body) + Space Mono (labels/mono) are expected to already
 * be loaded by the host page (as sterling.js's ensureFonts() does estate-wide). Since
 * the Cherokee/SMB app is a separate Flask template tree and font-loading there isn't
 * guaranteed, the @import below makes this file self-sufficient — same Google Fonts
 * query sterling.js uses (incl. the wdth axis instances the wordmark's font-stretch:118%
 * depends on), so the SMB widget renders byte-identical type to the rest of the estate.
 * Harmless no-op if the page already loaded these families (the browser dedupes).
 */
@import url('https://fonts.googleapis.com/css2?family=Archivo:wdth,wght@100,400;100,700;118,900&family=Space+Mono:wght@400;700&display=swap');

:root {
  --strl-paper:   #f2f1ea;                 /* panel/paper background, ink text sits on this */
  --strl-ink:     #0a0a0a;                 /* ink — text, launcher fill, borders, bars */
  --strl-lime:    #c8ff00;                 /* the ONE accent — use sparingly (dots, focus, active) */
  --strl-grotesk: "Archivo", system-ui, sans-serif;         /* display + body */
  --strl-mono:    "Space Mono", ui-monospace, monospace;    /* labels, mono chrome */
  --strl-kick:    #6a6a62;                 /* mid grey — eyebrow / status / secondary labels */
  --strl-faint:   #8a897f;                 /* faint grey — placeholders, faintest labels */
  --strl-rule:    rgba(10, 10, 10, 0.14);  /* hairline borders/dividers on paper */
}

#preacher-widget {
  position: fixed;
  right: 24px;
  bottom: 24px;
  z-index: 9999;
  font-family: var(--strl-grotesk);
}

/* ==========================================================================
   Launcher — the ink+lime "seal", matches sterling.js .seal. Square is KEPT
   (house brutalist style + canonical C never rounds it either — consistent
   with both constraints). Final shape here is the icon+label pill (the
   "D launcher" patch's effective shape in the dark original); the earlier
   circular-avatar #preacher-bubble/.preacher-bubble-dot/.preacher-bubble-ring
   sizing that patch superseded is not replayed.
   ========================================================================== */
#preacher-bubble {
  width: auto !important;
  height: 60px !important;
  border-radius: 0 !important;
  display: flex !important;
  flex-direction: row;
  align-items: stretch;
  padding: 0 !important;
  background: var(--strl-ink) !important;
  border: 2px solid var(--strl-lime) !important;
  overflow: visible !important;
  position: relative;
  cursor: pointer;
  /* Lighter than the dark original's shadow on purpose — that shadow fought a
     dark page for depth; on paper (or any page) the ink+lime seal is already
     the highest-contrast thing on screen, so it only needs a light lift, not
     a heavy glow. Judgment call — flag for reviewer sign-off. */
  box-shadow: 0 6px 18px rgba(10, 10, 10, 0.35);
  transition: transform 0.18s ease, box-shadow 0.18s ease;
}
#preacher-bubble:hover {
  transform: scale(1.04);
  box-shadow: 0 8px 22px rgba(10, 10, 10, 0.42), 0 0 0 4px rgba(200, 255, 0, 0.12);
}
#preacher-bubble:focus-visible {
  outline: 2px solid var(--strl-lime) !important;
  outline-offset: 3px;
}
/* Dead selector in current markup (no <img> remains inside #preacher-bubble —
   only .preacher-bubble-icon > svg.preacher-glyph today) but kept per the
   "never drop a selector" constraint in case an avatar image returns. */
#preacher-bubble img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  transform: scale(1.35);
  transform-origin: 50% 42%;
}
.preacher-bubble-label {
  display: flex; align-items: center; padding: 0 13px;
  /* Match the canonical launcher: an INK seal with LIME text (not lime-on-ink),
     so the "Ask Sterling" seal reads identically to the other estate surfaces. */
  background: var(--strl-ink);
  color: var(--strl-lime);
  font-family: var(--strl-mono);
  font-weight: 700;
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
  line-height: 1;
}
.preacher-bubble-icon {
  position: relative;
  width: 56px;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--strl-ink);
}
.preacher-glyph { display: block; width: 28px; height: 28px; } /* stroke=lime is inline SVG attr, unchanged — reads fine on ink */
.preacher-bubble-dot {
  position: absolute;
  width: 9px !important; height: 9px !important;
  bottom: -3px !important; right: -3px !important;
  border-radius: 50%;
  border: 2px solid var(--strl-ink) !important;
  background: var(--strl-lime) !important;
  transition: background 0.2s ease, box-shadow 0.2s ease;
}
/* Voice mode on — pulse the status dot. */
#preacher-widget.is-voice .preacher-bubble-dot {
  background: var(--strl-lime);
  box-shadow: 0 0 0 0 rgba(200, 255, 0, 0.6);
  animation: preacher-voice-dot 1.4s cubic-bezier(0.65, 0, 0.35, 1) infinite;
}
@keyframes preacher-voice-dot {
  0%, 100% { box-shadow: 0 0 0 0 rgba(200, 255, 0, 0.55); }
  50%      { box-shadow: 0 0 0 6px rgba(200, 255, 0, 0);  }
}

/* Recording ring — concentric pulse around the bubble while voice is hot. */
.preacher-bubble-ring {
  position: absolute;
  inset: -8px;
  border-radius: 50%;
  border: 2px solid transparent;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.3s ease;
}
#preacher-widget.is-voice .preacher-bubble-ring {
  opacity: 1;
  border-color: rgba(200, 255, 0, 0.55);
  animation: preacher-voice-ring 1.8s cubic-bezier(0.16, 1, 0.3, 1) infinite;
}
/* Speaking-back state. NOTE: named "cyan"/"is-speaking" throughout this file
   but the dark original's actual values here were already lime, not cyan —
   no distinct cyan color exists in the source to convert. Kept lime to match
   current live behavior; if a true distinct "speaking" accent was intended,
   that's a design decision beyond a reskin — flagged for reviewer. */
#preacher-widget.is-voice.is-speaking .preacher-bubble-ring {
  border-color: rgba(200, 255, 0, 0.65);
}
#preacher-widget.is-voice.is-speaking .preacher-bubble-dot {
  background: var(--strl-lime);
}
@keyframes preacher-voice-ring {
  0%   { transform: scale(1);    opacity: 0.85; }
  100% { transform: scale(1.45); opacity: 0;    }
}

/* ---- Action fan (voice / window) — floating chrome above the bubble ----
   Kept as ink-glass (not paper-glass): it's chrome attached to the ink
   launcher, not the paper panel, so it stays tonally part of the seal.
   Not part of the explicit brief — flagged for reviewer. */
.preacher-actions {
  position: absolute;
  bottom: 70px;
  right: 0;
  display: flex;
  flex-direction: column-reverse;
  align-items: flex-end;
  gap: 8px;
  pointer-events: none;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 0.22s cubic-bezier(0.16, 1, 0.3, 1),
              transform 0.22s cubic-bezier(0.16, 1, 0.3, 1);
}
#preacher-widget.preacher-actions-open .preacher-actions {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}
.preacher-action {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px 8px 10px;
  height: 38px;
  border-radius: 22px;
  background: rgba(10, 10, 10, 0.82);
  backdrop-filter: blur(14px) saturate(120%);
  -webkit-backdrop-filter: blur(14px) saturate(120%);
  border: 1px solid rgba(200, 255, 0, 0.28);
  color: var(--strl-paper);
  font-family: var(--strl-grotesk);
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.02em;
  cursor: pointer;
  box-shadow: 0 8px 22px rgba(10, 10, 10, 0.4);
  transition: transform 0.18s cubic-bezier(0.34, 1.56, 0.64, 1),
              border-color 0.18s ease,
              background 0.18s ease;
  white-space: nowrap;
}
.preacher-action:hover {
  transform: translateX(-4px);
  border-color: rgba(200, 255, 0, 0.55);
  background: rgba(10, 10, 10, 0.92);
}
.preacher-action svg { flex-shrink: 0; color: var(--strl-lime); }
.preacher-action[data-mode="voice"] svg { color: var(--strl-lime); }
.preacher-action-label { line-height: 1; }
#preacher-widget.is-voice .preacher-action[data-mode="voice"] {
  border-color: rgba(200, 255, 0, 0.55);
}
#preacher-widget.is-voice .preacher-action[data-mode="voice"] .preacher-action-label::after {
  content: " · stop";
  opacity: 0.7;
}

/* ==========================================================================
   Panel — paper card, 1px ink border, 6px ink top bar, soft shadow.
   Matches sterling.js .panel almost exactly. Background/border/backdrop-
   filter carry !important for the same host-reset-defeating reason the dark
   original needed it (see file header) — _brutal.css strips backgrounds
   estate-wide; without !important the panel goes transparent/illegible.
   ========================================================================== */
#preacher-panel {
  display: none;
  position: fixed;
  right: 24px;
  bottom: 96px;
  width: min(440px, calc(100vw - 32px));
  height: min(720px, calc(100dvh - 120px));
  margin: 0 !important;
  padding: 0 !important;
  background: var(--strl-paper) !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
  border: 1px solid var(--strl-ink) !important;
  border-radius: 0;
  /* Reuses the canonical Sterling C panel shadow verbatim (rgba base kept as
     0,0,0-equivalent 10,10,10 to stay inside this file's ink convention). */
  box-shadow: 0 30px 80px -30px rgba(10, 10, 10, 0.9);
  flex-direction: column;
  overflow: hidden;
  z-index: 1000;
  transform-origin: bottom right;
  transition:
    right 0.42s cubic-bezier(0.16, 1, 0.3, 1),
    bottom 0.42s cubic-bezier(0.16, 1, 0.3, 1),
    width 0.42s cubic-bezier(0.16, 1, 0.3, 1),
    height 0.42s cubic-bezier(0.16, 1, 0.3, 1),
    border-radius 0.42s cubic-bezier(0.16, 1, 0.3, 1),
    box-shadow 0.42s cubic-bezier(0.16, 1, 0.3, 1),
    border-color 0.42s cubic-bezier(0.16, 1, 0.3, 1);
}
/* Ink bar across the top of the panel — new rule (not in the dark original),
   required by the Sterling C brief; added per the explicit "you may add
   rules" allowance. */
#preacher-panel::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 6px;
  background: var(--strl-ink);
  pointer-events: none;
}
#preacher-panel.is-expanded {
  right: 0 !important;
  bottom: 0 !important;
  width: 100vw !important;
  height: 100vh !important;
  height: 100dvh !important;
  border-radius: 0 !important;
  border-color: transparent !important;
  box-shadow: none !important;
}
#preacher-panel.open {
  display: flex;
  animation: preacher-pop .32s cubic-bezier(0.16, 1, 0.3, 1) both;
}
@keyframes preacher-pop {
  from { opacity: 0; transform: scale(0.985); }
  to   { opacity: 1; transform: scale(1); }
}
#preacher-widget.is-open #preacher-bubble { display: none !important; }

/* ==========================================================================
   Panel header — eyebrow + wordmark. Background left transparent (paper
   shows through) rather than the dark original's forced-opaque ink bar:
   the Sterling C brief explicitly wants the eyebrow/wordmark sitting
   directly on paper, and _brutal.css already strips backgrounds by default
   — transparent here needs no !important fight, it's what the reset wants
   anyway. Deliberate deviation from the dark file's "final cascaded value"
   in favor of matching the canonical C reference; flagged for reviewer.
   ========================================================================== */
.preacher-panel-head {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 22px 32px;
  background: transparent;
  border-bottom: 1px solid var(--strl-rule);
  width: 100%;
  box-sizing: border-box;
}
.preacher-panel-head > * { max-width: none; }
.preacher-head-avatar {
  /* Sterling C has no header avatar — the wordmark IS the identity. Hiding this
     decorative glyph-circle matches the canonical panels + frees width so the
     STERLING wordmark can't collide with the Audit/expand/close controls.
     Per-message speaker avatars (.preacher-avatar-sm) are unaffected. */
  display: none !important;
  align-items: center;
  justify-content: center;
  width: 52px; height: 52px;
  border-radius: 50%;
  border: 1px solid rgba(200, 255, 0, 0.4);
  background: var(--strl-ink);
  flex-shrink: 0;
  overflow: hidden;
}
.preacher-head-avatar .preacher-glyph { width: 26px; height: 26px; }
/* Dead selector (avatar is now the glyph span above, not an <img>) — kept
   per the "never drop a selector" constraint. */
.preacher-head-avatar img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  transform: scale(1.35);
  transform-origin: 50% 42%;
}
.preacher-head-text { flex: 1; min-width: 0; overflow: hidden; }

/* Wordmark. The dark original's #preacher-panel-title held only "Sterling"
   as plain text (+ an optional ADMIN badge span) — no wrapper for a partial-
   outline "LING" treatment. CSS cannot select a substring of a text node, so
   the outlined-LING micro-detail from Sterling C is NOT achievable without a
   markup change (wrapping "LING" in a <span>/<i>). Delivered instead: the
   full wordmark weight/case/size/stretch treatment on the whole word. If a
   1-line markup edit ever wraps the tail in <i>, `.preacher-wordmark-tail`
   below is pre-built to receive it. FLAGGED — the single biggest visual gap
   from the canonical reference; reviewer should decide whether to greenlight
   a markup patch for the true split-outline.
   The eyebrow ("Frederick & Sons · Concierge") is generated content since
   markup can't be touched — satisfies the brief's explicit CSS-only
   allowance for that specific element. */
#preacher-panel-title {
  font-family: var(--strl-grotesk);
  font-weight: 900;
  font-stretch: 118%;
  text-transform: uppercase;
  letter-spacing: -0.02em;
  font-size: 26px;   /* SMB header also carries Audit/expand/close controls, so a touch smaller than the canonical 30px so it fits without collision */
  line-height: 0.9;
  color: var(--strl-ink);
  white-space: nowrap;
}
#preacher-panel-title::before {
  content: "Frederick & Sons · Concierge";
  display: block;
  margin-bottom: 6px;
  font-family: var(--strl-mono);
  font-weight: 700;
  font-stretch: normal;
  font-size: 9px;
  letter-spacing: 0.09em;   /* tightened so the full "FREDERICK & SONS · CONCIERGE" fits the panel head on 390px mobile (was clipping at 0.16em) */
  white-space: nowrap;
  text-transform: uppercase;
  color: var(--strl-kick);
}
/* Pre-built hook for a future markup edit: <span id="preacher-panel-title">
   Ster<i class="preacher-wordmark-tail">ling</i></span> would get the true
   Sterling-C outlined tail. No-op today (no markup targets this class). */
.preacher-wordmark-tail {
  font-style: normal;
  -webkit-text-stroke: 1.3px var(--strl-ink);
  color: transparent;
}

.preacher-head-sub {
  font-family: var(--strl-mono);
  font-size: 11px;
  color: var(--strl-kick);
  letter-spacing: 0.5px;
  text-transform: uppercase;
  margin-top: 4px;
}
.preacher-readout {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  letter-spacing: 0.12em;
}
/* Original default dot color was #00d886 (green) — a second, incidental
   accent color the brief's "keep the ONE lime accent" rule doesn't leave
   room for. Collapsed to lime rather than carried forward; deliberate
   color-collapse, not a mechanical flip — flagged for reviewer. */
.preacher-readout .dot {
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--strl-lime);
  box-shadow: 0 0 0 2px rgba(200, 255, 0, 0.18);
  animation: preacher-readout-pulse 2.4s cubic-bezier(0.65, 0, 0.35, 1) infinite;
}
.preacher-readout .dot.cyan {
  background: var(--strl-lime);
  box-shadow: 0 0 0 2px rgba(200, 255, 0, 0.20);
}
@keyframes preacher-readout-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.4; }
}
.preacher-admin-badge {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 6px;
  font-family: var(--strl-mono);
  font-size: 9px;
  font-weight: 700;
  font-stretch: normal; /* don't inherit the wordmark's 118% stretch onto this tiny tag */
  letter-spacing: 1px;
  color: var(--strl-lime);
  background: rgba(200, 255, 0, 0.12);
  border: 1px solid rgba(200, 255, 0, 0.55);
  border-radius: 2px;
  vertical-align: middle;
}
.preacher-head-expand,
.preacher-icon-btn,
#preacher-close {
  background: transparent;
  border: none;
  color: var(--strl-kick);
  cursor: pointer;
  padding: 4px 8px;
  font-size: 18px;
  line-height: 1;
  text-decoration: none;
  border-radius: 0;
}
.preacher-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  transition: background .18s ease, color .18s ease, transform .22s cubic-bezier(0.16, 1, 0.3, 1);
}
.preacher-head-expand:hover,
.preacher-icon-btn:hover,
#preacher-close:hover {
  background: var(--strl-rule);
  color: var(--strl-ink);
}
#preacher-panel.is-expanded #preacher-expand svg {
  transform: rotate(180deg);
}
#preacher-expand svg {
  transition: transform .28s cubic-bezier(0.16, 1, 0.3, 1);
}

/* ==========================================================================
   Log / empty-state / quick chips
   ========================================================================== */
.preacher-log {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 32px 24px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  width: 100%;
  max-width: 760px;
  margin: 0 auto;
  box-sizing: border-box;
}
.preacher-empty {
  color: var(--strl-ink);
  font-size: 14px;
  line-height: 1.6;
  padding: 4px 2px 4px;
  margin: 0;
  width: 100%;
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.preacher-empty p.preacher-greeting {
  margin: 0 0 14px;
  color: var(--strl-ink);
  font-size: 13.5px;
  text-align: left;
  letter-spacing: -0.005em;
  flex-shrink: 0;
}
/* Pre-existing copy from the dark original, byte-identical — NOT something
   introduced here. Flagged: "/ preacher · ready" is an internal-codename
   leak into user-facing chat copy (house rule: no internal codenames on any
   customer-facing surface). Out of scope for a stylesheet-only task to
   silently rewrite; surfaced for reviewer/owner to fix at the copy layer. */
.preacher-empty p.preacher-greeting::before {
  content: "/ sterling · ready";
  display: block;
  font-family: var(--strl-mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--strl-lime);
  margin-bottom: 8px;
}
.preacher-quick {
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex: 1;
  min-height: 0;
}
.preacher-chip {
  flex: 1;
  min-height: 36px;
}
.preacher-chip {
  appearance: none;
  background: none;
  border: 1px solid var(--strl-ink);
  color: var(--strl-ink);
  padding: 10px 14px;
  border-radius: 0;
  font-family: var(--strl-mono);
  font-size: 11.5px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-align: left;
  cursor: pointer;
  transition: border-color .18s cubic-bezier(0.65, 0, 0.35, 1),
              background .18s cubic-bezier(0.65, 0, 0.35, 1),
              color .18s cubic-bezier(0.65, 0, 0.35, 1),
              transform .18s cubic-bezier(0.34, 1.56, 0.64, 1);
}
/* ::before arrow uses currentColor (was a hardcoded lime) so it auto-flips
   ink<->paper with the chip's own hover-fill inversion below, instead of
   sitting as a mismatched lime mark on an ink-filled hover chip. Value-only
   fix, keeps the selector's existing mechanic intact. */
.preacher-chip::before {
  content: "→";
  color: currentColor;
  opacity: 0.7;
  margin-right: 8px;
  transition: transform .22s cubic-bezier(0.16, 1, 0.3, 1), opacity .18s;
  display: inline-block;
}
.preacher-chip:hover {
  background: var(--strl-ink);
  border-color: var(--strl-ink);
  color: var(--strl-paper);
}
.preacher-chip:hover::before {
  opacity: 1;
  transform: translateX(3px);
}
.preacher-chip:active { transform: scale(0.985); }
.preacher-empty p { margin: 0; }

/* ==========================================================================
   Turns / avatars / message content
   ========================================================================== */
.preacher-turn {
  display: flex;
  gap: 8px;
  max-width: 100%;
  animation: preacher-turn-in .32s cubic-bezier(0.16, 1, 0.3, 1) both;
}
.preacher-turn-user { flex-direction: row-reverse; }
@keyframes preacher-turn-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}
/* Small circular "who spoke" chip. NOTE: this markup has no separate mono
   text "who" label element the way sterling.js's canonical transcript does
   (its .msg .who is real markup that doesn't exist here) — this avatar chip
   is the ONLY role-indicator in the DOM. True "no avatar, mono who-label
   only" editorial parity is markup-constrained; styled instead as a small
   on-brand ink+lime chip rather than removed (removing it via display:none
   would leave turns with no visible speaker indicator at all). */
.preacher-avatar-sm {
  flex-shrink: 0;
  width: 24px; height: 24px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--strl-mono);
  font-size: 10px;
  font-weight: 700;
  overflow: hidden;
}
.preacher-avatar-sm.user {
  background: rgba(200, 255, 0, 0.18);
  color: #5a7a00; /* canonical Sterling C's user-label olive-green accent */
  border: 1px solid rgba(200, 255, 0, 0.4);
}
.preacher-avatar-sm.bot {
  display: flex; align-items: center; justify-content: center;
  padding: 0;
  background: var(--strl-ink);
  border: 1px solid rgba(200, 255, 0, 0.4);
}
.preacher-avatar-sm.bot .preacher-glyph { width: 15px; height: 15px; }
/* Dead selector (bot avatar is the glyph span above, not an <img>) — kept
   per the "never drop a selector" constraint. */
.preacher-avatar-sm.bot img {
  width: 100%; height: 100%; object-fit: cover;
  transform: scale(1.35);
  transform-origin: 50% 42%;
}

/* Editorial message treatment per brief: bot = left-rule inset, no bubble;
   user = solid ink bubble, paper text, right-aligned (already right-aligned
   via .preacher-turn-user's row-reverse, unchanged). Square corners
   (border-radius:0) on both — matches canonical C (no radius on .msg .txt
   there either) and the house brutalist convention; the old "tail" corner
   radius on the user bubble is dropped, it doesn't fit a square system. */
.preacher-bubble-msg {
  max-width: calc(100% - 36px);
  padding: 9px 13px;
  border-radius: 0;
  font-size: 13.5px;
  line-height: 1.5;
  white-space: pre-wrap;
  word-wrap: break-word;
  color: var(--strl-ink);
  letter-spacing: -0.005em;
}
.preacher-bubble-msg.user {
  background: var(--strl-ink);
  color: var(--strl-paper);
  border: none;
}
.preacher-bubble-msg.bot {
  background: transparent;
  border: none;
  border-left: 2px solid var(--strl-ink);
  padding-left: 11px;
}
.preacher-tool-note {
  margin-left: 32px;
  font-family: var(--strl-mono);
  font-size: 10px;
  color: var(--strl-kick);
  white-space: pre-wrap;
  padding: 2px 0;
}

/* ==========================================================================
   "Sterling is thinking…" pending indicator
   ========================================================================== */
.preacher-pending[hidden] { display: none !important; }
.preacher-pending {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 14px;
  color: var(--strl-kick);
  font-size: 11px;
  font-family: var(--strl-mono);
}
.preacher-pending .dot {
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--strl-lime);
  animation: preacher-pulse 1.2s infinite ease-in-out;
}
.preacher-pending .dot:nth-child(2) { animation-delay: 0.18s; }
.preacher-pending .dot:nth-child(3) { animation-delay: 0.36s; }
@keyframes preacher-pulse {
  0%, 80%, 100% { opacity: 0.2; transform: scale(0.8); }
  40%           { opacity: 1;   transform: scale(1.0); }
}

/* ==========================================================================
   Form / input / send / mic / voice picker
   Per brief: mono underline input (was a filled dark box), ink Send button
   with paper text (was inverted: lime bg / ink text in the dark original).
   NOTE: #preacher-input is a 2-row <textarea>, not a single-line <input>
   like the canonical demo — an underline-only textarea reads as a bigger
   visual departure than canonical's compact input. Flagged for a live check.
   ========================================================================== */
.preacher-form {
  display: flex;
  gap: 10px;
  padding: 18px 24px 24px;
  border-top: 1px solid var(--strl-rule);
  background: transparent;
  align-items: stretch;
  width: 100%;
  max-width: 760px;
  margin: 0 auto;
  box-sizing: border-box;
}
#preacher-input {
  flex: 1;
  padding: 14px 16px;
  border: none;
  border-bottom: 1px solid var(--strl-rule);
  border-radius: 0;
  background: transparent;
  color: var(--strl-ink);
  font-family: var(--strl-mono);
  font-size: 14px;
  line-height: 1.5;
  resize: none;
  box-sizing: border-box;
  min-height: 56px;
  max-height: 160px;
}
/* Not in the dark original (no explicit ::placeholder rule there — it relied
   on UA default). Added to match canonical C's explicit placeholder color
   and guarantee consistent cross-browser rendering on paper. */
#preacher-input::placeholder { color: var(--strl-faint); opacity: 1; }
#preacher-input:focus {
  outline: none;
  border-bottom-color: var(--strl-ink);
}
#preacher-send {
  padding: 0 22px;
  background: var(--strl-ink);
  border: none;
  border-radius: 0;
  color: var(--strl-paper);
  font-family: var(--strl-grotesk);
  font-weight: 900;
  font-size: 13px;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  cursor: pointer;
  align-self: stretch;
  min-width: 78px;
}
#preacher-send:disabled { opacity: 0.5; cursor: wait; }

/* ---- Premium voice picker (segmented control in panel header) ---- */
.preacher-voice-picker {
  display: inline-flex;
  gap: 4px;
  margin-left: 10px;
  padding: 2px;
  border-radius: 0;
  background: rgba(10, 10, 10, 0.04);
  border: 1px solid var(--strl-rule);
}
.preacher-voice-picker .vp-btn {
  appearance: none;
  background: transparent;
  border: 0;
  color: var(--strl-kick);
  font-family: inherit;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.04em;
  padding: 3px 7px;
  border-radius: 0;
  cursor: pointer;
  transition: background .12s, color .12s;
}
.preacher-voice-picker .vp-btn:hover { color: var(--strl-ink); }
.preacher-voice-picker .vp-btn.active {
  background: rgba(200, 255, 0, 0.18);
  color: #5a7a00;
}

/* ---- Mic button (hidden when browser doesn't support SpeechRecognition) ---- */
#preacher-mic {
  padding: 0 14px;
  background: transparent;
  border: 1px solid rgba(10, 10, 10, 0.18);
  border-radius: 0;
  color: var(--strl-kick);
  cursor: pointer;
  align-self: stretch;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 50px;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
#preacher-mic:hover {
  color: var(--strl-lime);
  border-color: rgba(200, 255, 0, 0.5);
}
#preacher-mic.recording {
  color: var(--strl-lime);
  border-color: rgba(200, 255, 0, 0.6);
  background: rgba(200, 255, 0, 0.08);
  animation: preacher-mic-pulse 1s ease-in-out infinite;
}
@keyframes preacher-mic-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(200, 255, 0, 0.5); }
  50%      { box-shadow: 0 0 0 6px rgba(200, 255, 0, 0); }
}

/* ==========================================================================
   Responsive — sizing/layout only, no new color decisions (colors flow from
   :root vars set once above). Bumped the mobile wordmark from the original's
   16px (tuned for the old 700-weight compact title) to 22px — the new
   900-weight/118%-stretch face needs more room to stay legible at small
   size; judgment call, flag for a live mobile check.
   ========================================================================== */
@media (max-width: 540px) {
  #preacher-widget {
    right: calc(16px + env(safe-area-inset-right));
    bottom: calc(20px + env(safe-area-inset-bottom));
  }
  #preacher-panel {
    inset: 0;
    width: 100vw;
    height: 100dvh;
    max-width: 100vw;
    max-height: 100dvh;
  }
  .preacher-panel-head { padding: 16px 18px; gap: 12px; }
  .preacher-head-avatar { width: 44px; height: 44px; }
  #preacher-panel-title { font-size: 22px; }
  .preacher-log { padding: 20px 16px; }
  .preacher-form { padding: 14px 16px 18px; gap: 8px; }
  #preacher-input { padding: 12px 14px; min-height: 50px; }
  #preacher-send { min-width: 64px; padding: 0 16px; }
  .preacher-bubble-label { display: none; }
}

/* Tap-delay kill — instant taps on mobile, no 300ms zoom hesitation. */
#preacher-bubble, #preacher-close, #preacher-send,
.preacher-head-expand, #preacher-input { touch-action: manipulation; }

/* Reduced motion — same two selector groups the dark original disabled,
   merged into one @media block (was split across two in the source; the
   cross-assigned animation/transition properties below are no-ops on the
   selectors that never used them, so this merge changes no behavior). */
@media (prefers-reduced-motion: reduce) {
  .preacher-turn,
  #preacher-panel.open { animation: none !important; }
  #preacher-bubble { transition: none !important; }
}
