/*
 * Two CSS token scopes — DO NOT mix.
 *
 *   --chatsap-*         declared on .chatsap-widget (chat surface)
 *   --chatsap-chrome-*  declared on .chatsap-preview (toolbar/dialog/tooltip)
 *
 * .chatsap-preview is a SIBLING of .chatsap-widget in the DOM, so vars
 * declared on the widget cannot reach the chrome via the cascade and
 * vice versa. When adding a token, declare it once per scope (light)
 * and once again in dark — never cross scopes.
 *
 * Light is default. Dark overrides apply when data-chatsap-theme="dark"
 * is set on the matching root element. The chrome block lives in
 * 18_chrome.css; this file declares the widget scope only.
 */

.chatsap-widget {
  --chatsap-teal-dark: #075E54;
  --chatsap-teal: #128C7E;
  --chatsap-green: #25D366;
  --chatsap-bubble-out: #DCF8C6;
  --chatsap-bubble-in: #FFFFFF;
  --chatsap-bubble-out-text: #111B21;
  --chatsap-bubble-in-text: #111B21;
  --chatsap-chat-bg: #ECE5DD;
  /* DEMO ONLY: external doodle asset. Production must ship an original
     pattern. SVG strokes are masked, so color is themable. */
  --chatsap-chat-doodle: url(/assets/chatsap/chat-doodle-light.svg?v=2);
  --chatsap-chat-doodle-size: 374px 666px;
  --chatsap-chat-doodle-repeat: repeat;
  --chatsap-meta: #667781;
  --chatsap-meta-out: #667781;
  --chatsap-tick-read: #4FC3F7;
  --chatsap-voice-icon: rgba(11, 20, 26, 0.55);
  --chatsap-voice-mic: #54656F;
  --chatsap-voice-bar-played: rgba(11, 20, 26, 0.85);
  --chatsap-voice-bar-unplayed: rgba(11, 20, 26, 0.35);
  --chatsap-input-bg: #F0F2F5;
  --chatsap-input-field-bg: #FFFFFF;
  --chatsap-input-icon: #54656F;
  --chatsap-frame-border: #111111;
  --chatsap-divider: #E5E7EB;
  --chatsap-text: #111B21;
  --chatsap-option-bg: rgba(255, 255, 255, 0.85);
  --chatsap-option-text: #075E54;
  --chatsap-option-leading: #075E54;
  --chatsap-option-hover: rgba(0, 0, 0, 0.04);
  --chatsap-quote-bar: #128C7E;
  --chatsap-quote-bg: rgba(0, 122, 90, 0.08);
  --chatsap-quote-bar-out: #128C7E;
  --chatsap-quote-bg-out: rgba(0, 0, 0, 0.10);
  --chatsap-quote-author-out: #128C7E;
  --chatsap-quote-text-out: rgba(11, 20, 26, 0.65);
  --chatsap-quote-highlight: rgba(18, 140, 126, 0.18);
  --chatsap-progress-label: rgba(255, 255, 255, 0.85);
  --chatsap-typing-dot: #9AA0A6;
  --chatsap-system-bubble-bg: rgba(225, 245, 254, 0.92);
  --chatsap-system-bubble-text: #075E54;
  --chatsap-day-divider-bg: rgba(225, 245, 254, 0.92);
  --chatsap-day-divider-text: #54656F;
  --chatsap-list-sheet-bg: #FFFFFF;
  --chatsap-section-title: #075E54;
  --chatsap-action-bg: #128C7E;
  --chatsap-action-bg-hover: #075E54;
  --chatsap-reaction-bg: rgba(255, 255, 255, 0.85);

  display: flex;
  justify-content: center;
  align-items: flex-start;
  padding: 1rem;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue",
    "Helvetica", "Roboto", "Arial", sans-serif;
  color: var(--chatsap-text);
  -webkit-font-smoothing: antialiased;
  font-size: 14px;
  line-height: 1.4;
}
/* ----------------------------- Phone frame ----------------------------- */

.chatsap-phone-frame {
  position: relative;
  width: 400px;
  height: 820px;
  background: var(--chatsap-chat-bg);
  border: 4px solid var(--chatsap-frame-border);
  border-radius: 3rem;
  box-shadow:
    0 20px 40px rgba(0, 0, 0, 0.18),
    0 6px 14px rgba(0, 0, 0, 0.12);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  isolation: isolate;
}

.chatsap-notch {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 180px;
  height: 28px;
  background: #000;
  border-bottom-left-radius: 16px;
  border-bottom-right-radius: 16px;
  z-index: 10;
}

/* No-frame mode: drop the mock phone chrome so hosts that already provide
 * a container (iframe, modal, sidebar) get just the chat surface.
 */
.chatsap-widget--no-frame .chatsap-phone-frame {
  border: 0;
  border-radius: 0;
  box-shadow: none;
  width: 100%;
  height: 100%;
  max-width: none;
}

.chatsap-widget--no-frame .chatsap-notch { display: none; }
.chatsap-widget--no-frame .chatsap-header { padding-top: 12px; }
/* -------------------------------- Header ------------------------------- */

.chatsap-header {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 28px 12px 10px;
  background: linear-gradient(180deg, var(--chatsap-teal-dark) 0%, var(--chatsap-teal) 100%);
  color: #fff;
  flex-shrink: 0;
}

.chatsap-header__back {
  background: transparent;
  border: 0;
  color: #fff;
  padding: 0;
  margin: 0;
  display: inline-flex;
  align-items: center;
  cursor: default;
}

.chatsap-header__avatar {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.18);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  overflow: hidden;
}

.chatsap-header__avatar-initial {
  font-weight: 600;
  font-size: 14px;
  color: #fff;
}

.chatsap-header__title {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-width: 0;
}

.chatsap-header__name {
  font-size: 16px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.chatsap-header__status {
  font-size: 12px;
  opacity: 0.85;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.chatsap-header__chip {
  display: inline-block;
  padding: 1px 6px;
  background: rgba(255, 255, 255, 0.2);
  border-radius: 8px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.02em;
}

.chatsap-header__actions {
  display: inline-flex;
  align-items: center;
  gap: 16px;
  color: #fff;
}

.chatsap-header__actions svg { flex-shrink: 0; }

/* Progress bar (optional, rendered when Step#progress is present). */
.chatsap-progress {
  position: relative;
  height: 3px;
  background: rgba(255, 255, 255, 0.18);
  flex-shrink: 0;
}
.chatsap-progress__fill {
  position: absolute;
  inset: 0 auto 0 0;
  background: var(--chatsap-green);
  width: 0;
  transition: width 240ms ease;
}
.chatsap-progress__label {
  position: absolute;
  right: 6px;
  top: -16px;
  font-size: 10px;
  /* Progress bar sits above the chat list but visually hangs from the
     header (which is dark-teal in light theme, dark-surface in dark).
     Use a near-white token so the label stays legible in both themes. */
  color: var(--chatsap-progress-label);
}
/* -------------------------------- Chat --------------------------------- */

/* Wrapper around the chat that hosts the custom overlay scrollbar.
   The chat itself has the native scrollbar fully hidden; we draw our own
   thumb on top so it never reserves layout width and never shows arrows. */
.chatsap-chat-wrap {
  position: relative;
  flex: 1 1 auto;
  display: flex;
  min-height: 0;
}

.chatsap-chat {
  flex: 1 1 auto;
  min-height: 0; /* allow shrinking below content size so overflow-y scrolls */
  overflow-y: scroll;
  overflow-x: hidden;
  padding: 10px 8px 6px;
  background-color: var(--chatsap-chat-bg);
  background-image: var(--chatsap-chat-doodle, none);
  background-size: var(--chatsap-chat-doodle-size, 374px 666px);
  background-repeat: var(--chatsap-chat-doodle-repeat, repeat);
  background-position: var(--chatsap-chat-doodle-position, 0 0);
  background-attachment: scroll;
  display: flex;
  flex-direction: column;
  gap: 4px;
  /* Hide the native scrollbar entirely; both axes, both browsers */
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.chatsap-chat::-webkit-scrollbar { width: 0; height: 0; display: none; }

/* Custom overlay thumb; drawn over the chat, hidden by default */
.chatsap-chat-thumb {
  position: absolute;
  right: 2px;
  width: 4px;
  border-radius: 2px;
  background: var(--chatsap-scrollbar-thumb, rgba(0, 0, 0, 0.35));
  opacity: 0;
  transition: opacity 200ms ease;
  pointer-events: none;
  z-index: 2;
}

.chatsap-chat-wrap.is-scrolling .chatsap-chat-thumb,
.chatsap-chat-wrap:hover .chatsap-chat-thumb {
  opacity: 1;
}

.chatsap-widget[data-chatsap-theme="dark"] .chatsap-chat-thumb,
.chatsap-widget[data-chatsap-theme="auto"] .chatsap-chat-thumb {
  --chatsap-scrollbar-thumb: rgba(255, 255, 255, 0.30);
  background: rgba(255, 255, 255, 0.30);
}
@media (prefers-color-scheme: light) {
  .chatsap-widget[data-chatsap-theme="auto"] .chatsap-chat-thumb {
    background: rgba(0, 0, 0, 0.35);
  }
}

/* Scroll-to-bottom button; floating chevron above the input row,
   shown only when the user has scrolled away from the latest message
   (matches the real WhatsApp pattern). Sits inside .chatsap-chat-wrap
   (positioning context) so it follows the chat surface, not the phone
   frame. */
.chatsap-scroll-to-bottom {
  position: absolute;
  bottom: 12px;
  right: 12px;
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: 50%;
  background: var(--chatsap-bubble-in);
  color: var(--chatsap-meta);
  cursor: pointer;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.10);
  z-index: 3;
  transition: opacity 180ms ease, transform 180ms ease;
}
.chatsap-scroll-to-bottom[hidden] {
  display: none;
}
.chatsap-scroll-to-bottom:hover {
  transform: translateY(-1px);
}
.chatsap-scroll-to-bottom:active {
  transform: scale(0.94);
}

/* Generic overlay scrollbar; used by the emoji picker body, list sheet,
   and any future scrollable surface. Activated by adding [data-chatsap-overlay-scroll]
   to a positioned wrapper that contains a [data-chatsap-overlay-target]
   (the actual scroller) and a .chatsap-overlay-thumb element. */
.chatsap-overlay-thumb {
  position: absolute;
  right: 2px;
  width: 4px;
  border-radius: 2px;
  background: rgba(0, 0, 0, 0.35);
  opacity: 0;
  transition: opacity 200ms ease;
  pointer-events: none;
  z-index: 2;
}

[data-chatsap-overlay-scroll].is-scrolling .chatsap-overlay-thumb,
[data-chatsap-overlay-scroll]:hover .chatsap-overlay-thumb {
  opacity: 1;
}

.chatsap-widget[data-chatsap-theme="dark"] .chatsap-overlay-thumb,
.chatsap-widget[data-chatsap-theme="auto"] .chatsap-overlay-thumb {
  background: rgba(255, 255, 255, 0.30);
}
@media (prefers-color-scheme: light) {
  .chatsap-widget[data-chatsap-theme="auto"] .chatsap-overlay-thumb {
    background: rgba(0, 0, 0, 0.35);
  }
}

/* ------------------------------- Bubbles ------------------------------- */

.chatsap-bubble-row {
  display: flex;
  width: 100%;
  position: relative;
}

.chatsap-bubble-row--in  { justify-content: flex-start; }
.chatsap-bubble-row--out { justify-content: flex-end; }

/* Highlight pulse; when a user replies to a message, the quoted bubble's
   row briefly fills the chat width with a green tint then fades out
   (mirrors WhatsApp's tap-on-quote UX). The pseudo-element extends past
   the chat padding so the band reaches the phone-frame edges. */
.chatsap-bubble-row--highlight::before {
  content: "";
  position: absolute;
  top: -2px;
  bottom: -2px;
  left: -8px;
  right: -8px;
  background: var(--chatsap-quote-highlight);
  pointer-events: none;
  animation: chatsap-quote-fade 1.4s ease-out forwards;
  z-index: 0;
}

.chatsap-bubble-row--highlight > * {
  position: relative;
  z-index: 1;
}

@keyframes chatsap-quote-fade {
  0%   { opacity: 1; }
  60%  { opacity: 1; }
  100% { opacity: 0; }
}

.chatsap-bubble {
  position: relative;
  max-width: 75%;
  padding: 7px 10px 5px;
  border-radius: 8px;
  box-shadow: 0 1px 0.5px rgba(0, 0, 0, 0.13);
  word-wrap: break-word;
}

.chatsap-bubble--in {
  background: var(--chatsap-bubble-in);
  color: var(--chatsap-bubble-in-text);
  border-top-left-radius: 8px;
}

.chatsap-bubble--in.chatsap-bubble--with-tail {
  border-top-left-radius: 0;
  margin-left: 8px;
}

.chatsap-bubble--in.chatsap-bubble--with-tail::before {
  content: "";
  position: absolute;
  top: 0;
  left: -8px;
  width: 0;
  height: 0;
  border-style: solid;
  border-width: 0 8px 8px 0;
  border-color: transparent var(--chatsap-bubble-in) transparent transparent;
  filter: drop-shadow(-1px 0 0 rgba(0, 0, 0, 0.06));
}

.chatsap-bubble--out {
  background: var(--chatsap-bubble-out);
  color: var(--chatsap-bubble-out-text);
  border-top-right-radius: 8px;
}

.chatsap-bubble--out .chatsap-bubble__meta { color: var(--chatsap-meta-out); }

.chatsap-bubble--out.chatsap-bubble--with-tail {
  border-top-right-radius: 0;
  margin-right: 8px;
}

.chatsap-bubble--out.chatsap-bubble--with-tail::before {
  content: "";
  position: absolute;
  top: 0;
  right: -8px;
  width: 0;
  height: 0;
  border-style: solid;
  border-width: 0 0 8px 8px;
  border-color: transparent transparent transparent var(--chatsap-bubble-out);
  filter: drop-shadow(1px 0 0 rgba(0, 0, 0, 0.06));
}

.chatsap-bubble__text {
  font-size: 14px;
  line-height: 19px;
  white-space: pre-wrap;
}

/* Reserve trailing space on the last line for the inline timestamp.
   This collapses naturally if the line is short enough that the
   timestamp would fit anyway. */
.chatsap-bubble__text::after {
  content: "";
  display: inline-block;
  width: 56px;
}

.chatsap-bubble--out .chatsap-bubble__text::after { width: 64px; /* room for ✓✓ */ }

.chatsap-bubble__text strong { font-weight: 600; }
.chatsap-bubble__text em     { font-style: italic; }
.chatsap-bubble__text s      { text-decoration: line-through; }

.chatsap-bubble__code-inline,
.chatsap-bubble__code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 13px;
  background: rgba(0, 0, 0, 0.06);
  border-radius: 4px;
}
.chatsap-bubble__code-inline {
  padding: 0 4px;
}
.chatsap-bubble__code {
  display: block;
  white-space: pre-wrap;
  padding: 6px 8px;
  margin: 4px 0;
}

.chatsap-bubble__quote-block {
  margin: 4px 0;
  padding: 2px 0 2px 10px;
  border-left: 4px solid var(--chatsap-quote-accent, currentColor);
  opacity: 0.85;
}

.chatsap-bubble__text ul.chatsap-bubble__list,
.chatsap-bubble__text ol.chatsap-bubble__list {
  margin: 4px 0 4px 18px;
  padding-left: 4px;
  list-style-position: outside !important;
}
.chatsap-bubble__text ul.chatsap-bubble__list {
  list-style-type: disc !important;
}
.chatsap-bubble__text ol.chatsap-bubble__list--ordered {
  list-style-type: decimal !important;
}
.chatsap-bubble__text .chatsap-bubble__list li {
  display: list-item !important;
  line-height: 19px;
  margin: 0;
  padding: 0;
}

.chatsap-bubble__text strong { font-weight: 700 !important; }
.chatsap-bubble__text em     { font-style: italic !important; }
.chatsap-bubble__text s      { text-decoration: line-through !important; }

.chatsap-bubble__meta {
  position: absolute;
  bottom: 3px;
  right: 8px;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-size: 11px;
  color: var(--chatsap-meta);
}

.chatsap-bubble__ticks {
  display: inline-flex;
  align-items: center;
  color: var(--chatsap-meta);
}

.chatsap-bubble__ticks--read {
  color: var(--chatsap-tick-read);
}

/* Reply quote inside a bubble. Default styling targets quotes in incoming
   bubbles. Outgoing-bubble quotes are styled below with a brighter accent
   bar matching WhatsApp's real interactive-button-reply look. */
.chatsap-bubble__quote {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 6px 8px;
  margin-bottom: 4px;
  border-left: 3px solid var(--chatsap-quote-bar);
  background: var(--chatsap-quote-bg);
  border-radius: 4px;
}

.chatsap-bubble--out .chatsap-bubble__quote {
  border-left-color: var(--chatsap-quote-bar-out);
  background: var(--chatsap-quote-bg-out);
}

.chatsap-bubble__quote[data-chatsap-quote-ref] {
  cursor: pointer;
}

.chatsap-bubble--out .chatsap-bubble__quote-author {
  color: var(--chatsap-quote-author-out);
}

.chatsap-bubble--out .chatsap-bubble__quote-text {
  color: var(--chatsap-quote-text-out);
}

.chatsap-bubble__quote-author {
  font-size: 12px;
  font-weight: 600;
  color: var(--chatsap-section-title);
}

.chatsap-bubble__quote-text {
  font-size: 13px;
  color: var(--chatsap-meta);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Reaction badges; small chip floating BELOW the bubble (not overlapping).
   Anchored to the same side as the bubble's tail (left for incoming,
   right for outgoing). Simple translucent pill, no border, light shadow. */
.chatsap-bubble__reactions {
  position: absolute;
  bottom: -22px;
  left: 4px;
  display: inline-flex;
  gap: 2px;
  z-index: 1;
}

.chatsap-bubble--out .chatsap-bubble__reactions { left: auto; right: 4px; }

.chatsap-reaction {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  background: var(--chatsap-reaction-bg, rgba(0, 0, 0, 0.08));
  border-radius: 999px;
  padding: 2px 6px 2px 5px;
  font-size: 11px;
  font-weight: 500;
  line-height: 14px;
  color: var(--chatsap-meta);
}

.chatsap-reaction-emoji { font-size: 13px; line-height: 1; }

/* Reserve vertical space for the floating chip below the bubble */
.chatsap-bubble-row:has(.chatsap-bubble__reactions) { margin-bottom: 18px; }

/* Media bubble: smaller padding so the image hugs the bubble edges (WhatsApp default) */
.chatsap-bubble--media {
  padding: 3px 3px 4px;
  min-width: 220px;
  max-width: 280px;
}

.chatsap-bubble--media .chatsap-bubble__text {
  padding: 2px 6px 0;
  padding-right: 56px;
}

.chatsap-bubble--media .chatsap-bubble__meta {
  bottom: 6px;
  right: 10px;
}

/* Lightbox; fullscreen viewer scoped to the phone-frame. Click on a
   video bubble or document card opens it; the X button (or Escape) closes.
   `position: absolute` + `inset: 0` confines it to the phone frame so
   we never bleed onto the host page. */
.chatsap-lightbox {
  position: absolute;
  inset: 0;
  z-index: 50;
  background: #000;
  display: flex;
  align-items: center;
  justify-content: center;
}

.chatsap-lightbox[hidden] { display: none; }

.chatsap-lightbox__close {
  position: absolute;
  top: 12px;
  right: 12px;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 0;
  background: rgba(0, 0, 0, 0.5);
  color: #fff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  z-index: 1;
}

.chatsap-lightbox__body {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Letterbox the video: contain inside the frame, preserving aspect. */
.chatsap-lightbox__video {
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: #000;
}

.chatsap-lightbox__pdf {
  width: 100%;
  height: 100%;
  border: 0;
  background: #fff;
}

.chatsap-lightbox__image {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

/* Image; tap-to-expand opens the lightbox. Button reset so the wrapper
   doesn't carry native button chrome. */
.chatsap-bubble__image {
  display: block;
  width: 100%;
  border: 0;
  padding: 0;
  margin: 0;
  background: transparent;
  border-radius: 6px;
  overflow: hidden;
  line-height: 0;
  cursor: pointer;
}
.chatsap-bubble__image img {
  display: block;
  width: 100%;
  max-width: 100%;
  border-radius: 6px;
  transition: transform 220ms ease;
}
.chatsap-bubble__image:hover img {
  transform: scale(1.02);
}

/* Video frame; poster + play overlay, before the user taps. Tapping
   opens the lightbox; the bubble itself never plays inline. */
.chatsap-bubble__video {
  position: relative;
  display: block;
  width: 100%;
  border: 0;
  padding: 0;
  border-radius: 6px;
  overflow: hidden;
  background: #000;
  line-height: 0;
  cursor: pointer;
}

.chatsap-bubble__video img,
.chatsap-bubble__video video {
  display: block;
  width: 100%;
  max-width: 100%;
  border-radius: 6px;
}

.chatsap-bubble__video-play {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 56px;
  height: 56px;
  border-radius: 50%;
  border: 0;
  background: rgba(11, 20, 26, 0.55);
  color: #fff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
}

.chatsap-bubble__video-duration {
  position: absolute;
  top: 6px;
  left: 6px;
  background: rgba(11, 20, 26, 0.55);
  color: #fff;
  font-size: 11px;
  padding: 2px 6px;
  border-radius: 4px;
  font-variant-numeric: tabular-nums;
  z-index: 1;
}

/* Document attachment card; non-media file (PDF, DOCX, XLSX, etc.).
   WhatsApp shows: file icon (left), filename + size · ext (middle),
   download icon (right). Clicking opens the file in a new tab. */
.chatsap-bubble--document {
  padding: 6px 6px 4px;
  min-width: 220px;
  max-width: 280px;
}

.chatsap-document-card {
  display: grid;
  grid-template-columns: 36px 1fr 28px;
  gap: 10px;
  align-items: center;
  background: rgba(0, 0, 0, 0.07);
  padding: 8px 10px;
  border-radius: 6px;
  text-decoration: none;
  color: inherit;
  transition: background 120ms ease;
}

.chatsap-bubble--out .chatsap-document-card {
  background: rgba(255, 255, 255, 0.10);
}

.chatsap-document-card:hover {
  background: rgba(0, 0, 0, 0.12);
}

.chatsap-document-card__icon {
  position: relative;
  width: 36px;
  height: 40px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--chatsap-meta);
}

.chatsap-document-card__ext-tag {
  position: absolute;
  bottom: 2px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--chatsap-section-title);
  color: #fff;
  font-size: 8px;
  font-weight: 700;
  padding: 1px 4px;
  border-radius: 2px;
  letter-spacing: 0.5px;
  line-height: 1;
}

.chatsap-document-card__icon--pdf .chatsap-document-card__ext-tag { background: #DC2626; }
.chatsap-document-card__icon--doc .chatsap-document-card__ext-tag,
.chatsap-document-card__icon--docx .chatsap-document-card__ext-tag { background: #2563EB; }
.chatsap-document-card__icon--xls .chatsap-document-card__ext-tag,
.chatsap-document-card__icon--xlsx .chatsap-document-card__ext-tag { background: #059669; }

.chatsap-document-card__body {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.chatsap-document-card__name {
  font-size: 13px;
  font-weight: 500;
  color: var(--chatsap-text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.chatsap-document-card__meta {
  font-size: 11px;
  color: var(--chatsap-meta);
  font-variant-numeric: tabular-nums;
}

.chatsap-document-card__action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--chatsap-meta);
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.05);
}

.chatsap-bubble--document .chatsap-bubble__meta {
  position: relative;
  bottom: auto;
  right: auto;
  justify-content: flex-end;
  padding: 0 4px;
}

.chatsap-bubble__media-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  height: 160px;
  background: rgba(0, 0, 0, 0.08);
  border-radius: 6px;
  color: var(--chatsap-meta);
  font-size: 12px;
  margin-bottom: 4px;
}

.chatsap-widget[data-chatsap-theme="dark"] .chatsap-bubble__media-placeholder,
.chatsap-widget[data-chatsap-theme="auto"] .chatsap-bubble__media-placeholder {
  background: rgba(255, 255, 255, 0.05);
}

/* Voice note (PTT; audio.voice: true on Cloud API).
   Outgoing-only in our preview: WhatsApp omits avatar/mic-badge on
   outgoing voice notes, so the layout simplifies to play | waveform
   on row 1, with duration + timestamp on row 2. */
/* Voice note layout (WhatsApp mobile/Web, May 2026):
   row 1: avatar w/ mic badge | play | progress (track = solid fill +
                                                 dotted unplayed + white playhead)
   row 2:                       duration (under play+progress)
   Timestamp + ticks float bottom-right via the regular __meta. */
.chatsap-bubble--voice {
  display: grid;
  grid-template-columns: 42px 26px 1fr;
  grid-template-rows: auto auto;
  column-gap: 10px;
  row-gap: 2px;
  align-items: center;
  width: min(82%, 300px);
  padding: 8px 10px 6px;
}

.chatsap-voice__avatar {
  grid-column: 1;
  grid-row: 1 / 3;
  position: relative;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  background: linear-gradient(135deg, #6B7B8C, #4A5867);
  color: #fff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  font-size: 16px;
  font-weight: 600;
  align-self: start;
  margin-top: -3px;
}

.chatsap-voice__avatar-initials {
  line-height: 1;
}

.chatsap-voice__mic-badge {
  position: absolute;
  right: -7px;
  bottom: 6px;
  width: 18px;
  height: 18px;
  background: transparent;
  color: var(--chatsap-section-title);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.chatsap-voice__play {
  grid-column: 2;
  grid-row: 1;
  width: 26px;
  height: 26px;
  border: 0;
  background: transparent;
  color: var(--chatsap-voice-icon, rgba(11, 20, 26, 0.55));
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  flex-shrink: 0;
  padding: 0;
  align-self: end;
  margin-bottom: -2px;
}

.chatsap-voice__progress {
  grid-column: 3;
  grid-row: 1;
  position: relative;
  height: 24px;
  display: flex;
  align-items: center;
  align-self: end;
  margin-bottom: -2px;
}

/* Waveform: SVG <rect> bars showing the audio envelope. Two layers stack
   on top of each other; both have the same geometry. The "played" layer
   is clip-pathed to --p% so the colored portion follows the playhead.
   preserveAspectRatio="none" on the SVG stretches the bars horizontally
   across the available width without subpixel snap or gap rounding ,
   the chart-like look stays clean at any container size. */
.chatsap-voice__waveform {
  position: absolute;
  left: 3px;
  right: 3px;
  top: 50%;
  height: 14px;
  transform: translateY(-50%);
  width: calc(100% - 6px);
  display: block;
  overflow: visible;
}

.chatsap-voice__waveform--unplayed rect {
  fill: var(--chatsap-voice-bar-unplayed, #FFFFFF);
}

/* Top layer: full-contrast "played" color, clipped to --p% of the progress
   container's width. The cut lines up with the playhead's center because
   the playhead is rendered with `transform: translate(-50%, ...)` at the
   same --p anchor. Change --p on .chatsap-voice__progress and the colored
   portion follows. */
.chatsap-voice__waveform--played {
  clip-path: inset(0 calc(100% - var(--p, 0%)) 0 0);
}

.chatsap-voice__waveform--played rect {
  fill: var(--chatsap-voice-bar-played, rgba(11, 20, 26, 0.35));
}

.chatsap-voice__playhead {
  position: absolute;
  top: 50%;
  left: var(--p, 0%);
  width: 10px;
  height: 10px;
  background: #FFFFFF;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
  z-index: 2;
}

.chatsap-voice__duration {
  grid-column: 3;
  grid-row: 2;
  font-size: 9px;
  color: var(--chatsap-meta);
  font-variant-numeric: tabular-nums;
}

/* Audio attachment (non-PTT; audio.voice: false on Cloud API, typical
   for business-shipped content). Same grid as .chatsap-bubble--voice so
   the two bubble types align visually in a thread. The avatar shows a
   headphones icon instead of voice's "initial + mic badge"; the
   progress is a linear track instead of a waveform. */
.chatsap-bubble--audio {
  display: grid;
  grid-template-columns: 42px 26px 1fr;
  grid-template-rows: auto auto;
  column-gap: 10px;
  row-gap: 2px;
  align-items: center;
  width: min(82%, 300px);
  padding: 8px 10px 6px;
}

.chatsap-audio__avatar {
  grid-column: 1;
  grid-row: 1 / 3;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  background: linear-gradient(135deg, #6B7B8C, #4A5867);
  color: #fff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  align-self: start;
  margin-top: -3px;
}

.chatsap-audio__play {
  grid-column: 2;
  grid-row: 1;
  width: 26px;
  height: 26px;
  border: 0;
  background: transparent;
  color: var(--chatsap-voice-icon, rgba(11, 20, 26, 0.55));
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  flex-shrink: 0;
  padding: 0;
  align-self: end;
  margin-bottom: -2px;
}

.chatsap-audio__progress {
  grid-column: 3;
  grid-row: 1;
  position: relative;
  height: 24px;
  display: flex;
  align-items: center;
  align-self: end;
  margin-bottom: -2px;
}

.chatsap-audio__progress-track {
  position: absolute;
  left: 3px;
  right: 3px;
  top: 50%;
  height: 3px;
  transform: translateY(-50%);
  background: var(--chatsap-voice-bar-unplayed, #FFFFFF);
  opacity: 0.45;
  border-radius: 2px;
}

.chatsap-audio__progress-fill {
  position: absolute;
  left: 3px;
  top: 50%;
  height: 3px;
  width: calc(var(--p, 0%) - 6px);
  transform: translateY(-50%);
  background: var(--chatsap-voice-bar-played, rgba(11, 20, 26, 0.75));
  border-radius: 2px;
  z-index: 1;
}

.chatsap-audio__playhead {
  position: absolute;
  top: 50%;
  left: var(--p, 0%);
  width: 10px;
  height: 10px;
  background: #FFFFFF;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
  z-index: 2;
}

.chatsap-audio__duration {
  grid-column: 3;
  grid-row: 2;
  font-size: 9px;
  color: var(--chatsap-meta);
  font-variant-numeric: tabular-nums;
}

/* Group consecutive bubbles from the same sender; only first carries tail */
.chatsap-bubble-row + .chatsap-bubble-row--in  .chatsap-bubble--in:not(.chatsap-bubble--with-tail),
.chatsap-bubble-row + .chatsap-bubble-row--out .chatsap-bubble--out:not(.chatsap-bubble--with-tail) {
  margin-left: 8px;
  margin-right: 8px;
}

/* ----------------------- Bubble context menu -------------------------- */

.chatsap-bubble-menu {
  position: absolute;
  z-index: 60;
  min-width: 200px;
  background: var(--chatsap-list-sheet-bg);
  border-radius: 12px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
  overflow: hidden;
  animation: chatsap-fade-in 120ms ease;
}

.chatsap-bubble-menu[hidden] { display: none; }

.chatsap-bubble-menu__reactions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2px;
  padding: 6px 8px;
  background: var(--chatsap-list-sheet-bg);
  border-bottom: 1px solid var(--chatsap-divider);
}

.chatsap-bubble-menu__reaction {
  width: 30px;
  height: 30px;
  border: 0;
  border-radius: 50%;
  background: transparent;
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background 100ms ease, transform 100ms ease;
  padding: 0;
  flex-shrink: 0;
}

.chatsap-bubble-menu__reaction:hover {
  background: rgba(0, 0, 0, 0.06);
  transform: scale(1.15);
}

.chatsap-widget[data-chatsap-theme="dark"] .chatsap-bubble-menu__reaction:hover,
.chatsap-widget[data-chatsap-theme="auto"] .chatsap-bubble-menu__reaction:hover {
  background: rgba(255, 255, 255, 0.08);
}

.chatsap-bubble-menu__reaction--more {
  font-size: 18px;
  font-weight: 600;
  color: var(--chatsap-text);
  background: rgba(0, 0, 0, 0.05);
}

.chatsap-widget[data-chatsap-theme="dark"] .chatsap-bubble-menu__reaction--more,
.chatsap-widget[data-chatsap-theme="auto"] .chatsap-bubble-menu__reaction--more {
  background: rgba(255, 255, 255, 0.08);
  color: var(--chatsap-text);
}

.chatsap-bubble-menu__list {
  list-style: none;
  margin: 0;
  padding: 4px 0;
}

.chatsap-bubble-menu__list button {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 9px 14px;
  background: transparent;
  border: 0;
  cursor: pointer;
  color: var(--chatsap-text);
  font-size: 14px;
  text-align: left;
  font-family: inherit;
}

.chatsap-bubble-menu__list button:hover {
  background: rgba(0, 0, 0, 0.04);
}

.chatsap-widget[data-chatsap-theme="dark"] .chatsap-bubble-menu__list button:hover,
.chatsap-widget[data-chatsap-theme="auto"] .chatsap-bubble-menu__list button:hover {
  background: rgba(255, 255, 255, 0.04);
}

.chatsap-bubble-menu__danger,
.chatsap-bubble-menu__danger * {
  color: #DC3545 !important;
}

.chatsap-bubble--menu-active {
  background: rgba(0, 168, 132, 0.18) !important;
}

/* ----------------------- Emoji picker (bottom sheet) ------------------- */

/* Sits above the input bar (its parent is the chat phone-frame); leaves
   the input bar visible so the user can keep typing while picking. */
.chatsap-emoji-picker {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 56px; /* above the input footer */
  z-index: 55;
  display: flex;
  align-items: stretch;
  pointer-events: none;
}
.chatsap-emoji-picker[hidden] { display: none; }

.chatsap-emoji-picker__panel {
  pointer-events: auto;
  width: 100%;
  height: 280px;
  background: var(--chatsap-list-sheet-bg);
  color: var(--chatsap-text);
  border-top-left-radius: 14px;
  border-top-right-radius: 14px;
  box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.25);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  animation: chatsap-slide-up 200ms cubic-bezier(0.2, 0.8, 0.2, 1);
}

/* When picker is open, give the chat list extra bottom padding so the last
   visible message sits just above the picker (not hidden under it). */
.chatsap-widget--picker-open .chatsap-chat {
  padding-bottom: 290px;
  scroll-padding-bottom: 290px;
  scroll-behavior: smooth;
}

.chatsap-emoji-picker__header {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border-bottom: 1px solid var(--chatsap-divider);
  flex-shrink: 0;
}

.chatsap-emoji-picker__keyboard {
  background: transparent;
  border: 0;
  padding: 6px;
  color: var(--chatsap-meta);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 6px;
  flex-shrink: 0;
}
.chatsap-emoji-picker__keyboard:hover { background: rgba(0, 0, 0, 0.06); color: var(--chatsap-text); }

.chatsap-widget[data-chatsap-theme="dark"] .chatsap-emoji-picker__keyboard:hover,
.chatsap-widget[data-chatsap-theme="auto"] .chatsap-emoji-picker__keyboard:hover {
  background: rgba(255, 255, 255, 0.06);
}

.chatsap-emoji-picker__search-wrap {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  background: var(--chatsap-input-field-bg);
  border-radius: 999px;
  padding: 0 10px;
  height: 32px;
  gap: 6px;
}

.chatsap-emoji-picker__search-icon { color: var(--chatsap-meta); flex-shrink: 0; }

.chatsap-emoji-picker__search {
  flex: 1 1 auto;
  min-width: 0;
  border: 0;
  outline: 0;
  background: transparent;
  font-size: 13px;
  color: var(--chatsap-text);
  font-family: inherit;
  padding: 0;
}

.chatsap-emoji-picker__search::placeholder { color: var(--chatsap-meta); }

.chatsap-emoji-picker__tabs {
  display: flex;
  align-items: center;
  gap: 0;
  padding: 4px;
  border-bottom: 1px solid var(--chatsap-divider);
  flex-shrink: 0;
  overflow-x: auto;
  scrollbar-width: none;
}
.chatsap-emoji-picker__tabs::-webkit-scrollbar { display: none; }

.chatsap-emoji-picker__tab {
  flex: 1 1 auto;
  min-width: 36px;
  background: transparent;
  border: 0;
  padding: 8px 4px;
  cursor: pointer;
  color: var(--chatsap-meta);
  border-bottom: 2px solid transparent;
  transition: border-color 100ms ease, color 100ms ease;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.chatsap-emoji-picker__tab svg { display: block; }

.chatsap-emoji-picker__tab.is-active {
  border-bottom-color: var(--chatsap-action-bg);
  color: var(--chatsap-action-bg);
}

.chatsap-emoji-picker__body-wrap {
  position: relative;
  flex: 1 1 auto;
  display: flex;
  min-height: 0;
}

.chatsap-emoji-picker__body {
  flex: 1 1 auto;
  overflow-y: scroll;
  padding: 8px 6px;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.chatsap-emoji-picker__body::-webkit-scrollbar { width: 0; height: 0; display: none; }

.chatsap-emoji-picker__loading {
  text-align: center;
  padding: 32px 0;
  color: var(--chatsap-meta);
  font-size: 13px;
}

.chatsap-emoji-section__title {
  margin: 4px 4px 6px;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--chatsap-meta);
}

.chatsap-emoji-grid {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  gap: 0;
}

.chatsap-emoji-cell {
  background: transparent;
  border: 0;
  padding: 6px 0;
  font-size: 22px;
  cursor: pointer;
  border-radius: 6px;
  line-height: 1;
  transition: background 80ms ease;
  font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji",
    "Twemoji Mozilla", "EmojiOne Color", sans-serif;
}

.chatsap-emoji-cell:hover { background: rgba(0, 0, 0, 0.06); }

.chatsap-widget[data-chatsap-theme="dark"] .chatsap-emoji-cell:hover,
.chatsap-widget[data-chatsap-theme="auto"] .chatsap-emoji-cell:hover {
  background: rgba(255, 255, 255, 0.06);
}

.chatsap-emoji-empty {
  text-align: center;
  padding: 32px 0;
  color: var(--chatsap-meta);
  font-size: 13px;
}
/* ------------------------------- Options -------------------------------
   WhatsApp interactive reply buttons render as a section attached to the
   bottom of the preceding bubble: same background, bottom-rounded corners,
   and a thin divider line on top. The .chatsap-options container is a
   sibling of the bubble in the DOM, so we pull it up with a negative
   margin to dock it visually.

   Multiple buttons stack with their own dividers between each (border-top
   on every button after the first). */
/* Options live INSIDE the preceding incoming bubble (sibling of __text/__meta).
   Negative side margins extend the section to the bubble's edges so the
   divider line and button hover backgrounds reach the rounded corners. */
.chatsap-options {
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
  margin: 6px -10px -5px -10px;
  border-bottom-left-radius: 8px;
  border-bottom-right-radius: 8px;
  overflow: hidden;
}

.chatsap-bubble--with-options {
  padding-bottom: 0;
}

.chatsap-bubble--with-options .chatsap-bubble__meta {
  position: static;
  display: flex;
  justify-content: flex-end;
  margin: 2px 0 0;
}

.chatsap-options--list-trigger {
  margin-top: 6px;
  border-radius: 8px;
}

.chatsap-option-button {
  position: relative;
  background: transparent;
  border: 0;
  border-top: 1px solid var(--chatsap-divider);
  padding: 11px 16px;
  font-size: 14px;
  font-weight: 500;
  color: var(--chatsap-option-text);
  cursor: pointer;
  transition: background 120ms ease, opacity 120ms ease;
  text-align: center;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}

/* All option buttons keep their top divider since they sit inside the bubble; the first one separates the bubble content from the options. */

.chatsap-options--list-trigger .chatsap-option-button {
  border-top: 0;
  background: var(--chatsap-bubble-in);
  border-radius: 8px;
}

.chatsap-option-button:hover { background: var(--chatsap-option-hover); }

.chatsap-option-button:disabled,
.chatsap-options--disabled .chatsap-option-button {
  opacity: 0.5;
  cursor: not-allowed;
}

.chatsap-option-button__leading {
  display: inline-flex;
  align-items: center;
  color: var(--chatsap-option-leading, var(--chatsap-option-text));
  /* Streamline reply icon's visual center sits below its viewBox center;
     pull it up so the arrowhead aligns with the label baseline. */
  margin-top: -2px;
}

.chatsap-option-button__label {
  flex: 0 0 auto;
  color: var(--chatsap-option-text);
}

/* --------------------------- Typing indicator -------------------------- */

/* The indicator lives in the partial as a sibling of .chatsap-chat-wrap
   (so it remains discoverable when the chat is cleared on rerender),
   but the controller moves it INTO the chat feed when shown; see
   #showTyping in chatsap_widget_controller.js. Styling is the same in
   both positions: a left-aligned chip with a small breathing margin.

   Putting it inside the feed is what prevents the long-standing bug
   where toggling visibility on a sibling node grew the input area
   downward and clipped the last visible messages. */
.chatsap-typing {
  display: flex;
  justify-content: flex-start;
  padding: 4px 8px;
}

.chatsap-typing[hidden] { display: none; }

.chatsap-typing__bubble {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: var(--chatsap-bubble-in);
  border-radius: 12px;
  padding: 8px 12px;
  box-shadow: 0 1px 0.5px rgba(0, 0, 0, 0.13);
}

.chatsap-typing__dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--chatsap-typing-dot);
  opacity: 0.4;
  animation: chatsap-typing-dot 1.4s infinite ease-in-out;
}

.chatsap-typing__dot:nth-child(2) { animation-delay: 0.2s; }
.chatsap-typing__dot:nth-child(3) { animation-delay: 0.4s; }

@keyframes chatsap-typing-dot {
  0%, 60%, 100% { opacity: 0.4; transform: translateY(0); }
  30%           { opacity: 1;   transform: translateY(-2px); }
}

/* -------------------------------- Input -------------------------------- */

.chatsap-input {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 6px 8px;
  background: var(--chatsap-input-bg);
  flex-shrink: 0;
}

.chatsap-input__icon {
  background: transparent;
  border: 0;
  padding: 4px;
  margin: 0;
  color: var(--chatsap-input-icon);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: default;
}

.chatsap-input__icon[hidden] { display: none; }

.chatsap-input__field-wrap {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  background: var(--chatsap-input-field-bg);
  border-radius: 20px;
  padding: 2px 6px;
  min-height: 36px;
  gap: 4px;
}

/* When the textarea grows past one line, drop icons to the bottom */
.chatsap-input__field-wrap:has(.chatsap-input__field.is-multiline) {
  align-items: flex-end;
  padding-bottom: 6px;
}

.chatsap-input__icon--leading,
.chatsap-input__icon--trailing {
  flex-shrink: 0;
}

.chatsap-input__icon--inline {
  color: var(--chatsap-input-icon);
  padding: 4px;
  flex-shrink: 0;
}

.chatsap-input__icon--leading { margin-right: 2px; }

.chatsap-input__send[hidden] { display: none; }

.chatsap-input__field {
  flex: 1 1 auto;
  min-width: 0;
  width: 100%;
  border: 0;
  outline: 0;
  background: transparent;
  font-size: 14px;
  line-height: 20px;
  padding: 0;
  color: var(--chatsap-text);
  font-family: inherit;
  resize: none;
  height: 20px;          /* one line; wrap padding handles the rest */
  max-height: 80px;      /* 4 lines */
  overflow: hidden;
  word-break: break-word;
  white-space: pre-wrap;
}

.chatsap-input__field.is-multiline {
  overflow-y: auto;
  scrollbar-width: none;
}
.chatsap-input__field.is-multiline::-webkit-scrollbar { width: 0; height: 0; }

.chatsap-input__field::-webkit-scrollbar { width: 0; height: 0; }

.chatsap-input__field::placeholder {
  color: #8696A0;
}

.chatsap-input__field { color: var(--chatsap-text); }

.chatsap-input__send {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--chatsap-action-bg, var(--chatsap-teal));
  color: #fff;
  border: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background 120ms ease;
  flex-shrink: 0;
}

.chatsap-input__send:hover  { background: var(--chatsap-action-bg-hover, var(--chatsap-teal-dark)); }
.chatsap-input__send:disabled {
  background: #BFD9D6;
  cursor: not-allowed;
}

/* Mic; same green pill as send, matching current WhatsApp design */
.chatsap-input__mic {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--chatsap-action-bg, var(--chatsap-teal));
  color: #fff;
  border: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
  flex-shrink: 0;
  padding: 0;
}

.chatsap-input__mic:hover { background: var(--chatsap-action-bg-hover, var(--chatsap-teal-dark)); }
.chatsap-input__mic[hidden] { display: none; }

/* ----------------------- System bubble (encryption etc) ---------------- */

.chatsap-system-bubble {
  align-self: center;
  max-width: 80%;
  margin: 6px auto 8px;
  padding: 7px 12px;
  background: var(--chatsap-system-bubble-bg);
  color: var(--chatsap-system-bubble-text);
  border-radius: 8px;
  font-size: 12px;
  line-height: 1.35;
  text-align: center;
  box-shadow: 0 1px 0.5px rgba(0, 0, 0, 0.13);
}

/* ------------------------------ Day divider ---------------------------- */

.chatsap-day-divider {
  display: flex;
  justify-content: center;
  margin: 8px 0;
}

.chatsap-day-divider span {
  background: var(--chatsap-day-divider-bg);
  color: var(--chatsap-day-divider-text);
  font-size: 12px;
  font-weight: 500;
  padding: 4px 10px;
  border-radius: 8px;
  box-shadow: 0 1px 0.5px rgba(0, 0, 0, 0.13);
}

/* ----------------------- List bottom sheet (modal) --------------------- */

.chatsap-list-sheet {
  position: absolute;
  inset: 0;
  z-index: 50;
  display: flex;
  align-items: flex-end;
  justify-content: stretch;
}

.chatsap-list-sheet[hidden] { display: none; }

.chatsap-list-sheet__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  animation: chatsap-fade-in 180ms ease;
}

.chatsap-list-sheet__panel {
  position: relative;
  width: 100%;
  max-height: 75%;
  background: var(--chatsap-list-sheet-bg, #FFFFFF);
  color: var(--chatsap-text);
  border-top-left-radius: 14px;
  border-top-right-radius: 14px;
  box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.25);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  animation: chatsap-slide-up 220ms cubic-bezier(0.2, 0.8, 0.2, 1);
}

.chatsap-list-sheet__handle {
  width: 36px;
  height: 4px;
  border-radius: 2px;
  background: var(--chatsap-divider);
  margin: 8px auto 4px;
  flex-shrink: 0;
}

.chatsap-list-sheet__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 16px 10px;
  border-bottom: 1px solid var(--chatsap-divider);
  flex-shrink: 0;
}

.chatsap-list-sheet__title {
  margin: 0;
  font-size: 15px;
  font-weight: 600;
  color: var(--chatsap-text);
}

.chatsap-list-sheet__close {
  background: transparent;
  border: 0;
  padding: 4px;
  color: var(--chatsap-meta);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.chatsap-list-sheet__body-wrap {
  position: relative;
  flex: 1 1 auto;
  display: flex;
  min-height: 0;
}

.chatsap-list-sheet__body {
  overflow-y: scroll;
  padding: 4px 0 12px;
  flex: 1 1 auto;
  cursor: grab;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  scrollbar-width: none;
  -ms-overflow-style: none;
  scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
  .chatsap-list-sheet__body { scroll-behavior: auto; }
}

.chatsap-list-sheet__body::-webkit-scrollbar { width: 0; height: 0; display: none; }

.chatsap-list-sheet__body.is-dragging {
  cursor: grabbing;
  user-select: none;
}

.chatsap-list-sheet__body.is-dragging .chatsap-list-row {
  cursor: grabbing;
  pointer-events: none;
}

/* Handle area is grabbable for drag-to-dismiss */
.chatsap-list-sheet__handle-zone {
  padding: 8px 0 4px;
  cursor: grab;
  touch-action: none;
}
.chatsap-list-sheet__handle-zone:active { cursor: grabbing; }

.chatsap-list-sheet__panel.is-dismissing {
  transition: transform 200ms cubic-bezier(0.4, 0, 1, 1);
}

.chatsap-list-section { padding: 4px 0; }

.chatsap-list-section__title {
  margin: 0;
  padding: 10px 16px 6px;
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--chatsap-section-title, #075E54);
}

.chatsap-list-row {
  width: 100%;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--chatsap-divider);
  padding: 12px 16px;
  text-align: left;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: 2px;
  color: var(--chatsap-text);
  transition: background 120ms ease;
}

.chatsap-list-row:hover { background: rgba(0, 0, 0, 0.04); }
.chatsap-list-row:last-child { border-bottom: 0; }

.chatsap-list-row__title {
  font-size: 14px;
  font-weight: 500;
}

.chatsap-list-row__desc {
  font-size: 12px;
  color: var(--chatsap-meta);
  line-height: 1.35;
}

@keyframes chatsap-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes chatsap-slide-up {
  from { transform: translateY(100%); }
  to   { transform: translateY(0); }
}
/* ---------------------------- Media renderers -------------------------- */

.chatsap-bubble--media {
  padding: 3px;
  overflow: hidden;
}

.chatsap-bubble--media img,
.chatsap-bubble--media video {
  display: block;
  max-width: 100%;
  border-radius: 6px;
}

.chatsap-bubble--media audio { width: 100%; }

.chatsap-document {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  background: rgba(0, 0, 0, 0.03);
  border-radius: 6px;
  text-decoration: none;
  color: inherit;
}

.chatsap-document__icon { color: #54656F; flex-shrink: 0; }

.chatsap-document__name {
  flex: 1 1 auto;
  font-size: 13px;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.chatsap-document__meta {
  font-size: 11px;
  color: var(--chatsap-meta);
}

/* ---------------------------- Completion state ------------------------- */

.chatsap-completion {
  margin: 12px 8px;
  padding: 12px;
  background: #FFF7D6;
  border-radius: 8px;
  text-align: center;
  font-size: 13px;
  color: #54656F;
  box-shadow: 0 1px 0.5px rgba(0, 0, 0, 0.13);
}

/* ----------------------------- Responsive ----------------------------- */

@media (max-width: 380px) {
  .chatsap-widget { padding: 0; }
  .chatsap-phone-frame {
    width: 100%;
    height: 100vh;
    border-radius: 0;
    border: 0;
  }
  .chatsap-notch { display: none; }
  .chatsap-header { padding-top: 12px; }
}
/* ------------------------------ Dark theme ----------------------------- *
 * Applied when the widget root has [data-chatsap-theme="dark"], OR when
 * theme="auto" and the host page's color scheme is dark.
 * Hex values mirror WhatsApp's dark mode (chat bg #0B141A, header #202C33,
 * incoming bubble #202C33, outgoing bubble #005C4B).
 */

.chatsap-widget[data-chatsap-theme="dark"],
.chatsap-widget[data-chatsap-theme="auto"] {
  --chatsap-teal-dark: #1F2C33;
  --chatsap-teal: #202C33;
  --chatsap-green: #25D366; /* brand constant, kept declared for explicit theme parity */
  --chatsap-bubble-out: #005C4B;
  --chatsap-bubble-in: #202C33;
  --chatsap-bubble-out-text: #E9EDEF;
  --chatsap-bubble-in-text: #E9EDEF;
  --chatsap-chat-bg: #0B141A;
  --chatsap-chat-doodle: url(/assets/chatsap/chat-doodle-dark.svg?v=2);
  --chatsap-chat-doodle-size: 374px 666px;
  --chatsap-chat-doodle-repeat: repeat;
  --chatsap-meta: #8696A0;
  --chatsap-meta-out: #aebac1;
  --chatsap-tick-read: #53BDEB;
  --chatsap-voice-icon: rgba(233, 237, 239, 0.85);
  --chatsap-voice-mic: rgba(233, 237, 239, 0.85);
  --chatsap-voice-bar-played: #FFFFFF;
  --chatsap-voice-bar-unplayed: rgba(233, 237, 239, 0.45);
  --chatsap-input-bg: #1F2C33;
  --chatsap-input-field-bg: #2A3942;
  --chatsap-input-icon: #AEBAC1;
  --chatsap-frame-border: #000000;
  --chatsap-divider: #2A3942;
  --chatsap-text: #E9EDEF;
  --chatsap-option-bg: rgba(32, 44, 51, 0.88);
  --chatsap-option-text: #00A884;
  --chatsap-option-leading: #00A884;
  --chatsap-option-hover: rgba(255, 255, 255, 0.04);
  --chatsap-quote-bar: #00A884;
  --chatsap-quote-bg: rgba(255, 255, 255, 0.06);
  --chatsap-quote-bar-out: #06CF9C;
  --chatsap-quote-bg-out: rgba(0, 0, 0, 0.18);
  --chatsap-quote-author-out: #06CF9C;
  --chatsap-quote-text-out: rgba(233, 237, 239, 0.65);
  --chatsap-quote-highlight: rgba(0, 168, 132, 0.20);
  --chatsap-progress-label: rgba(255, 255, 255, 0.85);
  /* (Preview chrome dark vars moved to .chatsap-preview[data-chatsap-theme="dark"]
    ; see "TOKENS; chrome" block.) */
  --chatsap-typing-dot: #8696A0;
  --chatsap-system-bubble-bg: rgba(27, 41, 47, 0.92);
  --chatsap-system-bubble-text: #25D366;
  --chatsap-day-divider-bg: rgba(27, 41, 47, 0.92);
  --chatsap-day-divider-text: #AEBAC1;
  --chatsap-list-sheet-bg: #1F2C33;
  --chatsap-section-title: #00A884;
  --chatsap-action-bg: #00A884;
  --chatsap-action-bg-hover: #008E72;
  --chatsap-reaction-bg: rgba(32, 44, 51, 0.92);
}

/* "auto" only flips when host page is in dark mode */
@media (prefers-color-scheme: light) {
  .chatsap-widget[data-chatsap-theme="auto"] {
    --chatsap-teal-dark: #075E54;
    --chatsap-teal: #128C7E;
    --chatsap-green: #25D366;
    --chatsap-bubble-out: #DCF8C6;
    --chatsap-bubble-in: #FFFFFF;
    --chatsap-bubble-out-text: #111B21;
    --chatsap-bubble-in-text: #111B21;
    --chatsap-chat-bg: #ECE5DD;
    --chatsap-chat-doodle: url(/assets/chatsap/chat-doodle-light.svg?v=2);
    --chatsap-chat-doodle-size: 374px 666px;
    --chatsap-chat-doodle-repeat: repeat;
    --chatsap-meta: #667781;
    --chatsap-meta-out: #667781;
    --chatsap-tick-read: #4FC3F7;
    --chatsap-voice-icon: rgba(11, 20, 26, 0.55);
    --chatsap-voice-mic: #54656F;
    --chatsap-voice-bar-played: rgba(11, 20, 26, 0.85);
    --chatsap-voice-bar-unplayed: rgba(11, 20, 26, 0.35);
    --chatsap-input-bg: #F0F2F5;
    --chatsap-input-field-bg: #FFFFFF;
    --chatsap-input-icon: #54656F;
    --chatsap-frame-border: #111111;
    --chatsap-divider: #E5E7EB;
    --chatsap-text: #111B21;
    --chatsap-option-bg: rgba(255, 255, 255, 0.85);
    --chatsap-option-text: #075E54;
    --chatsap-option-leading: #075E54;
    --chatsap-option-hover: rgba(0, 0, 0, 0.04);
    --chatsap-quote-bar: #128C7E;
    --chatsap-quote-bg: rgba(0, 122, 90, 0.08);
    --chatsap-quote-bar-out: #128C7E;
    --chatsap-quote-bg-out: rgba(0, 0, 0, 0.10);
    --chatsap-quote-author-out: #128C7E;
    --chatsap-quote-text-out: rgba(11, 20, 26, 0.65);
    --chatsap-quote-highlight: rgba(18, 140, 126, 0.18);
    --chatsap-progress-label: rgba(255, 255, 255, 0.85);
    /* (--chatsap-chrome-* tokens belong on .chatsap-preview, not here.) */
    --chatsap-typing-dot: #9AA0A6;
    --chatsap-system-bubble-bg: rgba(225, 245, 254, 0.92);
    --chatsap-system-bubble-text: #075E54;
    --chatsap-day-divider-bg: rgba(225, 245, 254, 0.92);
    --chatsap-day-divider-text: #54656F;
    --chatsap-list-sheet-bg: #FFFFFF;
    --chatsap-section-title: #075E54;
    --chatsap-action-bg: #128C7E;
    --chatsap-action-bg-hover: #075E54;
    --chatsap-reaction-bg: rgba(255, 255, 255, 0.85);
  }
}

/* Dark sheet hover */
.chatsap-widget[data-chatsap-theme="dark"] .chatsap-list-row:hover,
.chatsap-widget[data-chatsap-theme="auto"] .chatsap-list-row:hover {
  background: rgba(255, 255, 255, 0.04);
}
@media (prefers-color-scheme: light) {
  .chatsap-widget[data-chatsap-theme="auto"] .chatsap-list-row:hover {
    background: rgba(0, 0, 0, 0.04);
  }
}

/* --------------------------- Theme toggle (3-way) ---------------------- */

/* Segmented theme toggle; three pill segments inside a tinted track,
   with a sliding indicator behind the active option. The indicator is
   positioned via translateX (set in chatsap_preview.js#wireTheme) so the
   animation works for any variable width and survives DOM reflows.

   The track is kept even inside the toolbar capsule: the inner pill is
   what makes "pick one of three" obvious; without it the segmented
   control reads as three loose icons. */
.chatsap-theme-toggle {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0;
  padding: 3px;
  background: rgba(11, 20, 26, 0.06);
  border-radius: 999px;
  border: 1px solid rgba(11, 20, 26, 0.06);
}

.chatsap-theme-toggle__indicator {
  position: absolute;
  top: 3px;
  left: 0;
  width: 28px;
  height: 28px;
  border-radius: 999px;
  background: var(--chatsap-chrome-toggle-active-bg, #128C7E);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.20), 0 0 0 1px rgba(255, 255, 255, 0.10) inset;
  transform: translateX(0);
  transition: transform 280ms cubic-bezier(0.34, 1.36, 0.64, 1),
              width 200ms ease;
  pointer-events: none;
  z-index: 0;
}

.chatsap-theme-toggle__btn {
  position: relative;
  z-index: 1;
  width: 28px;
  height: 28px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: #54656F;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  transition: color 200ms ease, transform 180ms cubic-bezier(0.34, 1.56, 0.64, 1);
}

.chatsap-theme-toggle__btn:hover { color: #111B21; }
.chatsap-theme-toggle__btn:active { transform: scale(0.92); }

.chatsap-theme-toggle__btn[aria-pressed="true"] {
  color: var(--chatsap-chrome-toggle-active-text, #FFFFFF);
}

.chatsap-theme-toggle__btn:focus-visible {
  outline: 2px solid var(--chatsap-chrome-focus, #128C7E);
  outline-offset: 2px;
}

.chatsap-theme-toggle__btn svg { display: block; }

/* Dark page wrapper: tweak toggle palette so it stays legible */
@media (prefers-color-scheme: dark) {
  .chatsap-theme-toggle {
    background: rgba(255, 255, 255, 0.08);
    border-color: rgba(255, 255, 255, 0.10);
  }
  .chatsap-theme-toggle__btn { color: #AEBAC1; }
  .chatsap-theme-toggle__btn:hover { color: #E9EDEF; }
}

.chatsap-preview-stack {
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* Preview host; semantic wrapper only. Hosts decide page layout/background. */
.chatsap-preview-host {
  display: flex;
  justify-content: center;
}

/* ---------------------------- Preview chrome --------------------------- *
 * Wrapper produced by chatsap_preview_chrome(...). Includes a floating
 * topbar with optional close/restart icons + theme toggle, and a stage
 * that holds the fluid-scaled phone frame.
 *
 * Hierarchy boundary:
 *   The gem owns ONLY its own controls (toolbar, dialog, tooltip, theme
 *   indicator). Page background, full-viewport sizing, and host theming
 *   belong to the HOST app. We don't set position/inset, page-level
 *   background, or padding that assumes a viewport. The host places
 *   .chatsap-preview wherever it wants and decides the surrounding
 *   visuals (including dark-mode page colors).
 *
 * 2026 visual direction (chrome only):
 *   - subtle glass-morphism on the toolbar (translucent + backdrop blur)
 *   - pill-shaped icon buttons with soft hover halos
 *   - generous horizontal spacing so the chrome breathes
 */
/* TOKENS; chrome
   Single source of truth for --chatsap-chrome-* tokens. Do NOT mirror
   these into .chatsap-widget; they're consumed by elements (toolbar,
   dialog, tooltip) that are siblings of the widget, not descendants.

   Hierarchy boundary: the gem styles only its own controls (toolbar,
   dialog, tooltip). The full-page background, canvas, and any glows
   are the HOST's responsibility; the host wraps .chatsap-preview in
   whatever layout it wants. We do not set position, inset, or page
   background here. Light/dark theming of the host page is also the
   host's concern (it can react to data-chatsap-theme on .chatsap-preview
   if it wants to follow the toggle). */
.chatsap-preview {
  /* Light theme (default) */
  --chatsap-chrome-toolbar-bg: rgba(255, 255, 255, 0.92);
  --chatsap-chrome-toolbar-border: rgba(11, 20, 26, 0.12);
  --chatsap-chrome-toolbar-divider: rgba(11, 20, 26, 0.18);
  --chatsap-chrome-toolbar-segment-hover: rgba(11, 20, 26, 0.08);
  --chatsap-chrome-iconbtn-rest-bg: rgba(11, 20, 26, 0.04);
  --chatsap-chrome-iconbtn-text: #111B21;
  --chatsap-chrome-iconbtn-shadow: rgba(11, 20, 26, 0.10);
  --chatsap-chrome-iconbtn-highlight: rgba(255, 255, 255, 0.9);
  --chatsap-chrome-toggle-active-bg: #128C7E;
  --chatsap-chrome-toggle-active-text: #FFFFFF;
  --chatsap-chrome-tooltip-bg: rgba(17, 27, 33, 0.92);
  --chatsap-chrome-tooltip-text: #FFFFFF;
  --chatsap-chrome-tooltip-border: rgba(255, 255, 255, 0.06);
  --chatsap-chrome-focus: #128C7E;

  /* Animation tuning; change these once and the cascade stays coherent. */
  --chatsap-chrome-anim-base:   320ms;
  --chatsap-chrome-anim-step:    80ms;
  --chatsap-chrome-easing:      cubic-bezier(0.22, 0.61, 0.36, 1);
  --chatsap-chrome-easing-pop:  cubic-bezier(0.22, 1.36, 0.36, 1);

  display: flex;
  flex-direction: column;
  /* No height: 100% / position: fixed here on purpose. The host sizes
     this wrapper by placing it in its own layout (e.g., a flex parent or
     a grid cell with a defined height). If the host wants the legacy
     full-viewport behavior, it can add .chatsap-preview--fullscreen. */
  opacity: 0;
  animation: chatsap-preview-fouc-fallback 0s linear 1.5s forwards;
}
@keyframes chatsap-preview-fouc-fallback {
  to { opacity: 1; }
}
.chatsap-preview--ready {
  animation: chatsap-preview-fade-in var(--chatsap-chrome-anim-base) var(--chatsap-chrome-easing) both;
}

/* Opt-in modifier for hosts that want the gem to take over the full
   viewport (the previous default). The host can still skip this and
   place .chatsap-preview wherever it likes; the modifier is purely
   convenience for "I just want a fullscreen preview page". */
.chatsap-preview--fullscreen {
  position: fixed;
  inset: 0;
  overflow: hidden;
  isolation: isolate;
}

/* TOKENS; chrome (dark)
   Applied when the host (or the FOUC guard in _preview_chrome.html.erb)
   tags the preview root with data-chatsap-theme="dark". The :has()
   fallback covers cases where only the widget got the attribute.
   Tokens cover only chrome surfaces; page background remains untouched
   so the host owns it (see hierarchy note above). */
.chatsap-preview[data-chatsap-theme="dark"],
.chatsap-preview:has(.chatsap-widget[data-chatsap-theme="dark"]) {
  --chatsap-chrome-toolbar-bg: rgba(20, 30, 38, 0.88);
  --chatsap-chrome-toolbar-border: rgba(255, 255, 255, 0.14);
  --chatsap-chrome-toolbar-divider: rgba(255, 255, 255, 0.20);
  --chatsap-chrome-toolbar-segment-hover: rgba(255, 255, 255, 0.12);
  --chatsap-chrome-iconbtn-rest-bg: rgba(255, 255, 255, 0.06);
  --chatsap-chrome-iconbtn-text: #E9EDEF;
  --chatsap-chrome-iconbtn-shadow: rgba(0, 0, 0, 0.55);
  --chatsap-chrome-iconbtn-highlight: rgba(255, 255, 255, 0.10);
  --chatsap-chrome-toggle-active-bg: #00A884;
  --chatsap-chrome-tooltip-bg: rgba(245, 247, 250, 0.95);
  --chatsap-chrome-tooltip-text: #111B21;
  --chatsap-chrome-tooltip-border: rgba(11, 20, 26, 0.08);
  --chatsap-chrome-focus: #00A884;
}

@keyframes chatsap-preview-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* Entry animation. We animate ONLY opacity/translateY here; never the
   `transform: scale(...)` channel; because chatsap_preview.js#wireFit
   writes a `transform: scale(N)` inline on this element to keep it sized
   as a sibling of the phone. A keyframe ending in `transform: scale(1)`
   would override the inline scale (CSS animations with fill-mode: both
   beat element.style), so the topbar would render at its natural size
   while the phone shrunk on zoom. Don't add `scale` (or any non-translate
   transform) to this keyframe. */
.chatsap-preview__topbar {
  animation: chatsap-preview-toolbar-fade-in
             calc(var(--chatsap-chrome-anim-base) + 160ms)
             var(--chatsap-chrome-easing-pop)
             var(--chatsap-chrome-anim-step) both;
}
@keyframes chatsap-preview-toolbar-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.chatsap-preview__stage {
  animation: chatsap-preview-stage-in
             calc(var(--chatsap-chrome-anim-base) + 220ms)
             var(--chatsap-chrome-easing)
             calc(var(--chatsap-chrome-anim-step) * 2) both;
}
@keyframes chatsap-preview-stage-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
  .chatsap-preview,
  .chatsap-preview__topbar,
  .chatsap-preview__stage {
    animation: none;
  }
}

/* Layout host for the toolbar. Inspired by how .chatsap-preview__fit
   reserves space for the phone: this element holds the SCALED width
   and height (set by wireFit in chatsap_preview.js) so the page flow
   reflects the toolbar's visible size. The actual visual capsule is
   .chatsap-preview__toolbar, a child that gets `transform: scale()`.

   We set `width` and `height` from JS; no padding here (would
   double-count once JS reserves the scaled size). The host does NOT
   carry the entry animation transform (the inner toolbar would, but
   we keep transforms off it too; see comment on __toolbar). */
.chatsap-preview__topbar {
  flex: 0 0 auto;
  align-self: center;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  background: transparent;
  margin-top: 4px;
}

/* The toolbar itself is the visible container; glass capsule that wraps
   every control so they read as one cohesive component.

   Sized as a sibling of the phone: kept on a single horizontal line at
   its natural content width, then visually scaled by wireFit() (in
   chatsap_preview.js) so it shrinks together with the phone on zoom or
   narrow viewports. The host (.chatsap-preview__topbar) reserves layout
   space matching the scaled width; see wireFit for the math.

   transform-origin anchors at bottom center so JS scaling pulls the
   capsule TOWARD the phone (no growing gap as it shrinks). */
.chatsap-preview__toolbar {
  display: inline-flex;
  align-items: center;
  flex-wrap: nowrap;
  white-space: nowrap;
  width: max-content;
  height: 48px;
  padding: 6px 8px;
  border: 1px solid var(--chatsap-chrome-toolbar-border);
  border-radius: 999px;
  background: var(--chatsap-chrome-toolbar-bg);
  box-shadow:
    0 1px 0 var(--chatsap-chrome-iconbtn-highlight) inset,
    0 12px 40px rgba(11, 20, 26, 0.14),
    0 2px 8px rgba(11, 20, 26, 0.08);
  transform-origin: bottom center;
}
@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .chatsap-preview__toolbar {
    backdrop-filter: blur(20px) saturate(180%);
    -webkit-backdrop-filter: blur(20px) saturate(180%);
  }
}

/* Each section inside the toolbar (close, theme group, restart). The
   divider is rendered as a 1px-wide pseudo-element with vertical breathing
   room, so it visually separates without abutting the buttons. */
.chatsap-preview__section {
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 0 8px;
  position: relative;
}
.chatsap-preview__section:first-child  { padding-left: 4px; }
.chatsap-preview__section:last-child   { padding-right: 4px; }

/* Explicit divider control; host-rendered visual gap, zero-width box
   so it doesn't add visible content but still triggers the sibling
   divider line via the `+ ::before` rule below. */
.chatsap-preview__section--break {
  width: 0;
  padding: 0 6px;
}

.chatsap-preview__section + .chatsap-preview__section::before {
  content: "";
  position: absolute;
  left: 0;
  top: 8px;
  bottom: 8px;
  width: 1px;
  background: var(--chatsap-chrome-toolbar-divider);
}

/* Optional switch (e.g. AI grading on/off); sits inline in the toolbar
   between dividers, with a label and a track-and-thumb pattern that
   scales with the chrome's accent color. */
.chatsap-preview__switch {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 0 4px;
  cursor: pointer;
  user-select: none;
  font-size: 13px;
  color: var(--chatsap-chrome-iconbtn-text);
}
.chatsap-preview__switch-input {
  /* Hide the native checkbox without taking it out of layout flow in a
     way that pollutes the parent's positioning context. clip-path is
     accessibility-friendly (still focusable) and doesn't trigger weird
     ancestor reflows. */
  position: absolute;
  inset: 0;
  opacity: 0;
  margin: 0;
  cursor: pointer;
}
.chatsap-preview__switch-track {
  position: relative;
  width: 32px;
  height: 18px;
  background: var(--chatsap-chrome-toolbar-divider);
  border-radius: 999px;
  transition: background 200ms ease;
  flex: 0 0 auto;
}
.chatsap-preview__switch-thumb {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 14px;
  height: 14px;
  background: #fff;
  border-radius: 50%;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
  transition: transform 200ms cubic-bezier(0.34, 1.56, 0.64, 1);
}
/* Use :has() so the checked state is read off the parent label; robust
   to the input being absolute-positioned (can't rely on adjacent-sibling
   selector when the input is out of flow). */
.chatsap-preview__switch:has(.chatsap-preview__switch-input:checked) .chatsap-preview__switch-track {
  background: var(--chatsap-chrome-toggle-active-bg);
}
.chatsap-preview__switch:has(.chatsap-preview__switch-input:checked) .chatsap-preview__switch-thumb {
  transform: translateX(14px);
}
.chatsap-preview__switch:has(.chatsap-preview__switch-input:focus-visible) .chatsap-preview__switch-track {
  outline: 2px solid var(--chatsap-chrome-focus);
  outline-offset: 2px;
}
.chatsap-preview__switch-label {
  white-space: nowrap;
}

/* Side icon buttons (close, restart); pill-shaped with a soft tint at
   rest so they read as buttons even before hover. Inspired by macOS
   Sonoma toolbar buttons: visible affordance, no harsh outline. */
.chatsap-preview__iconbtn {
  position: relative;
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: 999px;
  background: var(--chatsap-chrome-iconbtn-rest-bg);
  color: var(--chatsap-chrome-iconbtn-text);
  cursor: pointer;
  transition:
    background 180ms ease,
    color 180ms ease,
    transform 180ms cubic-bezier(0.34, 1.56, 0.64, 1);
  text-decoration: none;
}
.chatsap-preview__iconbtn:hover {
  background: var(--chatsap-chrome-toolbar-segment-hover);
}
.chatsap-preview__iconbtn:active {
  transform: scale(0.92);
}
.chatsap-preview__iconbtn:focus-visible {
  outline: 2px solid var(--chatsap-chrome-focus);
  outline-offset: 2px;
}

/* Custom tooltip; replaces the native browser title with a styled chip
   that matches the chrome's glass aesthetic. Reads the label from
   data-chatsap-tip; the host element keeps aria-label for screen readers.
   data-chatsap-tip-side="start"|"end" repositions near viewport edges
   (set by chatsap_preview.js#wireTooltipFlip). */
.chatsap-preview [data-chatsap-tip] {
  position: relative;
}
.chatsap-preview [data-chatsap-tip]::after {
  content: attr(data-chatsap-tip);
  position: absolute;
  top: calc(100% + 10px);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  padding: 6px 10px;
  font-size: 12px;
  font-weight: 500;
  line-height: 1.2;
  white-space: nowrap;
  color: var(--chatsap-chrome-tooltip-text);
  background: var(--chatsap-chrome-tooltip-bg);
  border: 1px solid var(--chatsap-chrome-tooltip-border);
  border-radius: 8px;
  box-shadow: 0 6px 20px var(--chatsap-chrome-iconbtn-shadow);
  opacity: 0;
  pointer-events: none;
  /* Asymmetric: appear after a short hover delay (avoid flicker), but
     disappear quickly when mouse leaves so it never lingers stale. */
  transition: opacity 120ms ease 60ms, transform 120ms ease 60ms;
  z-index: 10;
}
@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .chatsap-preview [data-chatsap-tip]::after {
    backdrop-filter: blur(14px) saturate(160%);
    -webkit-backdrop-filter: blur(14px) saturate(160%);
  }
}
.chatsap-preview [data-chatsap-tip]::before {
  content: "";
  position: absolute;
  top: calc(100% + 4px);
  left: 50%;
  width: 8px;
  height: 8px;
  background: var(--chatsap-chrome-tooltip-bg);
  border-left: 1px solid var(--chatsap-chrome-tooltip-border);
  border-top: 1px solid var(--chatsap-chrome-tooltip-border);
  transform: translateX(-50%) rotate(45deg) translateY(4px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 120ms ease 60ms, transform 120ms ease 60ms;
  z-index: 11;
}
.chatsap-preview [data-chatsap-tip]:hover::after,
.chatsap-preview [data-chatsap-tip]:focus-visible::after {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
  transition-delay: 320ms;
}
.chatsap-preview [data-chatsap-tip]:hover::before,
.chatsap-preview [data-chatsap-tip]:focus-visible::before {
  opacity: 1;
  transform: translateX(-50%) rotate(45deg) translateY(0);
  transition-delay: 320ms;
}

/* Auto-flip; when JS detects the tooltip would overflow the viewport, it
   sets data-chatsap-tip-side. We anchor the bubble to the matching edge
   instead of centering it. */
.chatsap-preview [data-chatsap-tip][data-chatsap-tip-side="start"]::after { left: 0; transform: translateY(4px); }
.chatsap-preview [data-chatsap-tip][data-chatsap-tip-side="start"]:hover::after,
.chatsap-preview [data-chatsap-tip][data-chatsap-tip-side="start"]:focus-visible::after { transform: translateY(0); }
.chatsap-preview [data-chatsap-tip][data-chatsap-tip-side="end"]::after   { left: auto; right: 0; transform: translateY(4px); }
.chatsap-preview [data-chatsap-tip][data-chatsap-tip-side="end"]:hover::after,
.chatsap-preview [data-chatsap-tip][data-chatsap-tip-side="end"]:focus-visible::after { transform: translateY(0); }
/* Hide the arrow when we flip; anchoring the bubble to the edge means the
   arrow no longer points cleanly at the button center. Cheaper than
   recalculating the arrow position dynamically. */
.chatsap-preview [data-chatsap-tip][data-chatsap-tip-side]::before { display: none; }

@media (prefers-reduced-motion: reduce) {
  .chatsap-preview [data-chatsap-tip]::after,
  .chatsap-preview [data-chatsap-tip]::before {
    transition: opacity 0s !important;
  }
}

.chatsap-preview__stage {
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Tight top padding so the toolbar visually meets the phone; sides and
     bottom keep breathing room for the soft drop shadow. */
  padding: 4px 24px 24px;
  position: relative;
}

.chatsap-preview__fit {
  flex: 0 0 auto;
  display: flex;
  align-items: flex-start;
  justify-content: center;
}

.chatsap-preview__fit .chatsap-phone-frame {
  transform-origin: top center;
  width: 400px;
  height: 820px;
  flex: 0 0 auto;
}

/* ----------------------------- Confirm dialog ------------------------- *
 * In-page confirmation modal used for destructive actions (currently:
 * restart). Matches the toolbar's glass aesthetic; replaces the native
 * window.confirm() so the chrome feels cohesive. */
.chatsap-preview__dialog {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.chatsap-preview__dialog[hidden] { display: none; }

.chatsap-preview__dialog-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(11, 20, 26, 0.32);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  animation: chatsap-preview-dialog-fade 180ms ease both;
}

.chatsap-preview__dialog-panel {
  position: relative;
  max-width: 360px;
  width: 100%;
  padding: 22px 22px 18px;
  background: var(--chatsap-chrome-toolbar-bg, #FFFFFF);
  border: 1px solid var(--chatsap-chrome-toolbar-border, rgba(11, 20, 26, 0.08));
  border-radius: 16px;
  box-shadow:
    0 1px 0 var(--chatsap-chrome-iconbtn-highlight, rgba(255, 255, 255, 0.9)) inset,
    0 24px 60px rgba(11, 20, 26, 0.25),
    0 4px 14px rgba(11, 20, 26, 0.10);
  color: var(--chatsap-chrome-iconbtn-text, #111B21);
  animation: chatsap-preview-dialog-pop 220ms cubic-bezier(0.34, 1.36, 0.64, 1) both;
}
@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .chatsap-preview__dialog-panel {
    backdrop-filter: blur(20px) saturate(180%);
    -webkit-backdrop-filter: blur(20px) saturate(180%);
  }
}

.chatsap-preview__dialog-title {
  margin: 0 0 6px;
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -0.01em;
}

.chatsap-preview__dialog-body {
  margin: 0 0 18px;
  font-size: 14px;
  line-height: 1.45;
  opacity: 0.78;
}

.chatsap-preview__dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}

.chatsap-preview__dialog-btn {
  appearance: none;
  border: 0;
  padding: 8px 14px;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: background 160ms ease, color 160ms ease, transform 140ms ease;
}
.chatsap-preview__dialog-btn:active { transform: scale(0.96); }
.chatsap-preview__dialog-btn:focus-visible {
  outline: 2px solid var(--chatsap-chrome-focus, #128C7E);
  outline-offset: 2px;
}

.chatsap-preview__dialog-btn--ghost {
  background: var(--chatsap-chrome-toolbar-segment-hover, rgba(11, 20, 26, 0.06));
  color: var(--chatsap-chrome-iconbtn-text, #111B21);
}
.chatsap-preview__dialog-btn--ghost:hover {
  background: rgba(11, 20, 26, 0.10);
}

.chatsap-preview__dialog-btn--primary {
  background: var(--chatsap-chrome-toggle-active-bg, #128C7E);
  color: var(--chatsap-chrome-toggle-active-text, #FFFFFF);
}
.chatsap-preview__dialog-btn--primary:hover {
  filter: brightness(1.08);
}

@keyframes chatsap-preview-dialog-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes chatsap-preview-dialog-pop {
  from { opacity: 0; transform: translateY(8px) scale(0.96); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .chatsap-preview__dialog-backdrop,
  .chatsap-preview__dialog-panel { animation: none; }
}
/*
 * Chatsap widget; visual layer entry point.
 *
 * Target: WhatsApp Android (stable, Material Design 3; post Jan/2025
 * redesign). The phone frame is a mock device; the chat UI inside is
 * Android-faithful, not Desktop/Web. Liquid Glass (rollout 2026 Q2) is
 * intentionally NOT mirrored.
 *
 * Hex values reflect WhatsApp's Android brand palette:
 *   #075E54 / #128C7E (header teal, light)
 *   #1F2C33 / #202C33 (header / surfaces, dark)
 *   #DCF8C6 (outgoing bubble, light) / #005C4B (outgoing bubble, dark)
 *   #ECE5DD (chat backdrop, light) / #0B141A (chat backdrop, dark)
 *   #128C7E (send/mic accent, light) / #00A884 (send/mic accent, dark)
 *
 * The actual rules live in numbered partials. The numeric prefix keeps
 * order stable under both this manifest and Rails' alphabetic
 * require_tree, so partials can be added without renumbering.
 *
 *   01_tokens         --chatsap-* widget tokens (light)
 *   02_frame          phone frame
 *   03_header         chat header
 *   04_chat           chat surface (background, scroll, doodle)
 *   05_bubbles        all bubble kinds
 *   06_bubble_menu    long-press / right-click bubble menu
 *   07_emoji_picker   bottom-sheet emoji picker
 *   08_options        interactive button + list option styling
 *   09_typing         "..." typing indicator
 *   10_input          input bar (textarea, send, mic)
 *   11_system         encryption notice and other system bubbles
 *   12_day_divider    "Today" / "Yesterday" chip in the chat
 *   13_list_sheet     full-screen list reply modal
 *   14_media          media bubble shared rules + completion + responsive
 *   15_dark           .chatsap-widget[data-chatsap-theme="dark"] overrides
 *   16_theme_toggle   3-way light / dark / auto pill (preview chrome only)
 *   17_chrome         --chatsap-chrome-* tokens + preview wrapper styles
 *   18_dialog         confirm dialog (restart prompt)
 *
 * Order matters: dark and chrome blocks override base tokens, so they
 * sit at the bottom.
 *
 * ===== PHASE 1.5 / OSS PRE-RELEASE TODOs =====
 *
 *   1. Replace the WhatsApp doodle pattern (--chatsap-chat-doodle, flagged
 *      DEMO ONLY in 04_chat.css) with an original Chatac-themed pattern.
 *      The current SVG mirrors Meta's wallpaper too closely for OSS use.
 *
 *   2. Token deduplication. Light, dark, and auto each redeclare the full
 *      token set; adding a token means editing it three times. Refactor
 *      to declare light once and override only the deltas in dark/auto.
 *
 *   3. Inline SVGs scattered in partials should move to the chatsap_icon
 *      helper or to a chatsap_inline_svg helper for the assets that don't
 *      fit the Material Symbols set.
 *
 *   4. Locale file: ship config/locales/en.yml with the chatsap.* keys so
 *      hosts that do not translate get sensible defaults without warnings.
 *


















 */
