{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"comment-thread","type":"registry:ui","title":"Comment Thread","description":"One comment with replies – an assistant reports what it did, folds open details and answers @mentions","dependencies":[],"files":[{"path":"registry/comment-thread/comment-thread.tsx","type":"registry:ui","content":"\"use client\";\n\nimport { useEffect, useId, useLayoutEffect, useRef, useState, type CSSProperties, type ReactNode, type RefObject } from \"react\";\n\n/*\n * Comment Thread – one comment with its replies, including an assistant that reports what it did, in a single\n * self-contained file. Assistant replies can fold open to show the details; replying shows a thinking state\n * while an async answer comes back. The styles are injected below, so no extra files are needed.\n */\n\nexport type ThreadAuthor = { name: string; avatar?: ReactNode | string; assistant?: boolean };\n\nexport type ThreadMessage = {\n  id: string;\n  author: ThreadAuthor;\n  createdAt: Date | number;\n  text: string;\n  /** Assistant replies: a short status line that folds open to show these details */\n  status?: string;\n  details?: string[];\n};\n\nexport type CommentThreadProps = {\n  title?: string;\n  messages: ThreadMessage[];\n  currentUser: ThreadAuthor;\n  /** The assistant that answers – used for the thinking state */\n  assistant?: ThreadAuthor;\n  /**\n   * Called with every new reply. Return a message (or a promise of one) to let the assistant answer;\n   * return nothing to just post the reply.\n   */\n  onReply?: (text: string) => ThreadMessage | Promise<ThreadMessage | void> | void;\n  onClose?: () => void;\n  className?: string;\n};\n\nfunction ago(time: number, now: number) {\n  const s = Math.max(0, Math.round((now - time) / 1000));\n  if (s < 45) return \"just now\";\n  const m = Math.round(s / 60);\n  if (m < 60) return `${m}min ago`;\n  const h = Math.round(m / 60);\n  if (h < 24) return `${h}h ago`;\n  const d = Math.round(h / 24);\n  if (d < 30) return `${d}d ago`;\n  return d < 365 ? `${Math.round(d / 30)}mo ago` : `${Math.round(d / 365)}y ago`;\n}\n\n// 1284 → \"1,284\"\nconst count = new Intl.NumberFormat(\"en\");\n\n/** Two initials from whole letters – skips emoji and stray spaces, so \"🦊 Fox\" gives \"F\" */\nconst initials = (name: string) =>\n  name\n    .split(/\\s+/)\n    .map((w) => Array.from(w).find((c) => /[\\p{L}\\p{N}]/u.test(c)))\n    .filter(Boolean)\n    .slice(0, 2)\n    .join(\"\")\n    .toUpperCase();\n\nexport function CommentThread({\n  title = \"Comment\",\n  messages: initial,\n  currentUser,\n  assistant,\n  onReply,\n  onClose,\n  className,\n}: CommentThreadProps) {\n  const [messages, setMessages] = useState(initial);\n  // Assistant replies that are there from the start come in a beat after the comment above them\n  const [firstIds] = useState(() => new Set(initial.filter((m) => m.author.assistant).map((m) => m.id)));\n  const [open, setOpen] = useState<Set<string>>(new Set());\n  const [draft, setDraft] = useState(\"\");\n  const [thinking, setThinking] = useState(false);\n  const [now, setNow] = useState(() => Date.now());\n  const listRef = useRef<HTMLDivElement>(null);\n  const morphRef = useSmoothHeight(listRef);\n\n  useEffect(() => {\n    const t = window.setInterval(() => setNow(Date.now()), 30_000);\n    return () => window.clearInterval(t);\n  }, []);\n\n  // Follow the conversation as it grows\n  useEffect(() => {\n    listRef.current?.scrollTo({ top: listRef.current.scrollHeight, behavior: \"smooth\" });\n  }, [messages.length, thinking]);\n\n  const send = async () => {\n    const text = draft.trim();\n    if (!text || thinking) return;\n    setDraft(\"\");\n    setNow(Date.now());\n    lockHeight(true);\n    setMessages((m) => [...m, { id: `m-${Date.now()}`, author: currentUser, createdAt: Date.now(), text }]);\n    const answer = onReply?.(text);\n    if (!answer) return;\n    setThinking(true);\n    try {\n      const reply = await answer;\n      if (reply) setMessages((m) => [...m, { ...reply, createdAt: Date.now() }]);\n    } finally {\n      setThinking(false);\n      setNow(Date.now());\n    }\n  };\n\n  // New messages keep the card at its height and the conversation scrolls up; folding details lets it grow again\n  const lockHeight = (on: boolean) => {\n    const list = listRef.current;\n    if (list) list.style.maxHeight = on ? `${list.offsetHeight}px` : \"\";\n  };\n\n  const toggle = (id: string) => {\n    lockHeight(false);\n    setOpen((o) => {\n      const next = new Set(o);\n      if (next.has(id)) next.delete(id);\n      else next.add(id);\n      return next;\n    });\n  };\n\n  return (\n    <>\n      <style href=\"ui-comment-thread\" precedence=\"default\">\n        {css}\n      </style>\n      <section className={[\"ui-ct\", className].filter(Boolean).join(\" \")} aria-label={title}>\n        <header className=\"ui-ct__head\">\n          <h3 className=\"ui-ct__title\" title={title} dir=\"auto\">\n            {title}\n          </h3>\n          <span className=\"ui-ct__count\">\n            {count.format(messages.length)} {messages.length === 1 ? \"message\" : \"messages\"}\n          </span>\n          {onClose && (\n            <button type=\"button\" className=\"ui-ct__icon-btn\" aria-label=\"Close comment\" onClick={onClose}>\n              <Icon d=\"m4 4 8 8M12 4l-8 8\" />\n            </button>\n          )}\n        </header>\n\n        <div className=\"ui-ct__card ui-ct__morph\" ref={morphRef}>\n        <div className=\"ui-ct__scroll\" ref={listRef} aria-live=\"polite\">\n          {messages.map((m) => {\n            const isOpen = open.has(m.id);\n            const command = /^\\/edit\\b/i.test(m.text.trim());\n            return (\n              <article key={m.id} className=\"ui-ct__msg\" data-delayed={firstIds.has(m.id) || undefined}>\n                <div className=\"ui-ct__meta\">\n                  <Avatar author={m.author} />\n                  <span className=\"ui-ct__name\" title={m.author.name} dir=\"auto\">\n                    {m.author.name}\n                  </span>\n                  <time className=\"ui-ct__time\" dateTime={new Date(m.createdAt).toISOString()}>\n                    {ago(+m.createdAt, now)}\n                  </time>\n                </div>\n                {m.text && (\n                  <p className=\"ui-ct__text\" dir=\"auto\">\n                    {command ? (\n                      <>\n                        <span className=\"ui-ct__command\">/Edit</span> {m.text.trim().replace(/^\\/edit\\s*/i, \"\")}\n                      </>\n                    ) : (\n                      m.text\n                    )}\n                  </p>\n                )}\n                {m.status && (\n                  <div className=\"ui-ct__status\">\n                    <button\n                      type=\"button\"\n                      className=\"ui-ct__status-btn\"\n                      aria-expanded={isOpen}\n                      disabled={!m.details?.length}\n                      onClick={() => toggle(m.id)}\n                    >\n                      <span className=\"ui-ct__check\">\n                        <Icon d=\"m4 8.3 2.6 2.6L12 5.4\" size={12} />\n                      </span>\n                      <span className=\"ui-ct__status-text\" title={m.status} dir=\"auto\">\n                        {m.status}\n                      </span>\n                      {!!m.details?.length && (\n                        <span className=\"ui-ct__chevron\">\n                          <Icon d=\"m4.5 6.25 3.5 3.5 3.5-3.5\" size={14} />\n                        </span>\n                      )}\n                    </button>\n                    {!!m.details?.length && (\n                      <div className=\"ui-ct__details\" data-open={isOpen || undefined} inert={!isOpen}>\n                        <ul>\n                          {m.details.map((d, i) => (\n                            <li key={i} dir=\"auto\" style={{ \"--i\": i } as CSSProperties}>\n                              {d}\n                            </li>\n                          ))}\n                        </ul>\n                      </div>\n                    )}\n                  </div>\n                )}\n              </article>\n            );\n          })}\n          {thinking && assistant && (\n            <article className=\"ui-ct__msg\" aria-label={`${assistant.name} is thinking`}>\n              <div className=\"ui-ct__meta\">\n                <Avatar author={assistant} />\n                <span className=\"ui-ct__name\">{assistant.name}</span>\n              </div>\n              <p className=\"ui-ct__thinking\">Thinking…</p>\n            </article>\n          )}\n        </div>\n        </div>\n\n        <form\n          className=\"ui-ct__composer\"\n          onSubmit={(e) => {\n            e.preventDefault();\n            send();\n          }}\n        >\n          <input\n            className=\"ui-ct__input\"\n            value={draft}\n            onChange={(e) => setDraft(e.target.value)}\n            placeholder={assistant ? `Reply, or ask @${assistant.name}…` : \"Add comment…\"}\n            aria-label=\"Reply\"\n          />\n          <button type=\"submit\" className=\"ui-ct__send\" aria-label=\"Send reply\" disabled={!draft.trim() || thinking}>\n            <Icon d=\"M8 13V3M3.5 7.5 8 3l4.5 4.5\" size={14} />\n          </button>\n        </form>\n      </section>\n    </>\n  );\n}\n\nfunction Avatar({ author }: { author: ThreadAuthor }) {\n  // A picture that fails to load falls back to the initials\n  const [failed, setFailed] = useState(false);\n  if (author.avatar && typeof author.avatar !== \"string\") return <span className=\"ui-ct__avatar\">{author.avatar}</span>;\n  if (typeof author.avatar === \"string\" && !failed) {\n    return <img className=\"ui-ct__avatar\" src={author.avatar} alt=\"\" width={24} height={24} loading=\"lazy\" onError={() => setFailed(true)} />;\n  }\n  return (\n    <span className=\"ui-ct__avatar ui-ct__avatar--initials\" aria-hidden=\"true\">\n      {initials(author.name)}\n    </span>\n  );\n}\n\n/** A simple assistant mark: a full circle with a blue-to-violet gradient – pass your own logo as `avatar` instead */\nexport function AssistantMark() {\n  const id = useId();\n  return (\n    <svg viewBox=\"0 0 24 24\" width=\"24\" height=\"24\" aria-hidden=\"true\">\n      <defs>\n        <linearGradient id={`${id}-fill`} x1=\"3\" y1=\"3\" x2=\"21\" y2=\"21\" gradientUnits=\"userSpaceOnUse\">\n          <stop offset=\"0\" stopColor=\"#5b9dff\" />\n          <stop offset=\"0.5\" stopColor=\"#2f6bff\" />\n          <stop offset=\"1\" stopColor=\"#8b5cf6\" />\n        </linearGradient>\n      </defs>\n      <circle cx=\"12\" cy=\"12\" r=\"12\" fill={`url(#${id}-fill)`} />\n    </svg>\n  );\n}\n\nconst Icon = ({ d, size = 16 }: { d: string; size?: number }) => (\n  <svg viewBox=\"0 0 16 16\" width={size} height={size} fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n    <path d={d} />\n  </svg>\n);\n\n/**\n * Lets a box glide to the height of its content instead of jumping: the outer box follows the inner one\n * with a height transition whenever the content grows or shrinks.\n */\nfunction useSmoothHeight(inner: RefObject<HTMLElement | null>) {\n  const outer = useRef<HTMLDivElement>(null);\n  useLayoutEffect(() => {\n    const o = outer.current;\n    const i = inner.current;\n    if (!o || !i) return;\n    const sync = () => {\n      o.style.height = `${i.offsetHeight}px`;\n    };\n    sync();\n    const ro = new ResizeObserver(sync);\n    ro.observe(i);\n    // Transitions switch on after the first measurement, so the first render doesn't animate\n    const frame = requestAnimationFrame(() => o.setAttribute(\"data-smooth\", \"\"));\n    return () => {\n      ro.disconnect();\n      cancelAnimationFrame(frame);\n    };\n  }, [inner]);\n  return outer;\n}\n\n/* ---------- Styles ---------- */\n\nconst css = /* css */ `\n.ui-ct {\n  --ui-ct-tray: var(--aui-subtle, #f0f0f0);\n  --ui-ct-card: var(--aui-surface, #ffffff);\n  --ui-ct-ink: var(--aui-ink, #171717);\n  --ui-ct-text: var(--aui-ink, #404040);\n  --ui-ct-muted: var(--aui-muted, #8f8f8f);\n  --ui-ct-accent: var(--aui-blue, #4fb0fe);\n  --ui-ct-focus: var(--aui-focus, rgba(0, 96, 226, 0.7));\n  --ui-ct-ok: var(--aui-success, #1e8a4f);\n  --ui-ct-accent-text: var(--aui-blue, #4fb0fe);\n  --ui-ct-border: var(--aui-border, #e5e5e5);\n  --ui-ct-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);\n  --ui-ct-hover: var(--aui-subtle, rgba(0, 0, 0, 0.05));\n  --ui-ct-row-hover: var(--aui-subtle, #f5f5f5);\n  --ui-ct-initials: #eef7ff;\n  --ui-ct-dot: #d4d4d4;\n  --ui-ct-subtle: var(--aui-placeholder, #a3a3a3);\n  --ui-ct-avatar-ring: rgba(0, 0, 0, 0.06);\n  --ui-ct-ease: var(--aui-ease, cubic-bezier(0.22, 1, 0.36, 1));\n  box-sizing: border-box;\n  width: 100%;\n  max-width: 420px;\n  /* Like the Chat Composer: a gray tray with heading and reply field, the white card sits on top of it */\n  background: var(--ui-ct-tray);\n  /* The gray tray frames the white card on every side */\n  padding: 6px;\n  border-radius: calc(var(--aui-radius-lg, 16px) + 6px);\n  font-family: var(--aui-font, \"Inter\", ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif);\n  color: var(--ui-ct-ink);\n  -webkit-font-smoothing: antialiased;\n}\n.ui-ct *, .ui-ct *::before, .ui-ct *::after { box-sizing: border-box; }\n.ui-ct button { margin: 0; font: inherit; color: inherit; cursor: pointer; }\n.ui-ct button:focus-visible { outline: 2px solid var(--ui-ct-focus); outline-offset: 2px; }\n\n.ui-ct__head {\n  display: flex;\n  align-items: center;\n  gap: 10px;\n  min-height: 46px;\n  padding: 6px 10px 6px 18px;\n}\n/* A long title takes two lines at most – the count and close stay in place */\n.ui-ct__title { display: -webkit-box; min-width: 0; overflow: hidden; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow-wrap: anywhere; margin: 0; font-size: 15px; font-weight: 500; line-height: 22px; }\n.ui-ct__count { flex: none; margin-right: auto; white-space: nowrap; font-size: 12.5px; color: var(--ui-ct-muted); }\n.ui-ct__icon-btn {\n  display: grid;\n  place-items: center;\n  width: 28px;\n  height: 28px;\n  padding: 0;\n  border: 0;\n  border-radius: calc(var(--aui-radius-sm, 7px) + 1px);\n  background: transparent;\n  color: var(--ui-ct-muted) !important;\n  transition: background-color 140ms ease, color 140ms ease;\n}\n.ui-ct__icon-btn:hover { background: var(--ui-ct-hover); color: var(--ui-ct-ink) !important; }\n\n.ui-ct__card {\n  background: var(--ui-ct-card);\n  border: 1px solid var(--ui-ct-border);\n  border-radius: var(--aui-radius-lg, 16px);\n  box-shadow: var(--ui-ct-shadow);\n}\n.ui-ct__scroll {\n  display: grid;\n  gap: 18px;\n  align-content: start;\n  min-height: var(--ui-ct-min-height, 0px);\n  max-height: var(--ui-ct-max-height, 340px);\n  padding: 16px 18px 18px;\n  overflow-y: auto;\n  scrollbar-width: thin;\n}\n/* Each message builds up piece by piece: name row, text, status – the assistant's first reply a beat later */\n.ui-ct__msg { --ui-ct-d: 0ms; min-width: 0; }\n.ui-ct__msg[data-delayed] { --ui-ct-d: 700ms; }\n.ui-ct__msg > * { animation: ui-ct-in 420ms var(--ui-ct-ease) both; animation-delay: var(--ui-ct-d); }\n.ui-ct__msg > :nth-child(2) { animation-delay: calc(var(--ui-ct-d) + 80ms); }\n.ui-ct__msg > :nth-child(3) { animation-delay: calc(var(--ui-ct-d) + 160ms); }\n.ui-ct__meta { display: flex; align-items: center; gap: 9px; min-width: 0; }\n.ui-ct__avatar {\n  display: grid;\n  place-items: center;\n  flex: none;\n  width: 24px;\n  height: 24px;\n  border-radius: 50%;\n  object-fit: cover;\n  overflow: hidden;\n}\nimg.ui-ct__avatar { box-shadow: 0 0 0 1px var(--ui-ct-avatar-ring); }\n.ui-ct__avatar svg { width: 100%; height: 100%; }\n.ui-ct__avatar--initials { background: var(--ui-ct-initials); font-size: 9px; font-weight: 600; color: var(--ui-ct-accent-text); }\n.ui-ct__name { min-width: 0; overflow: hidden; font-size: 14px; font-weight: 500; line-height: 20px; white-space: nowrap; text-overflow: ellipsis; }\n.ui-ct__time { flex: none; margin-left: auto; white-space: nowrap; font-size: 12.5px; color: var(--ui-ct-muted); font-variant-numeric: tabular-nums; }\n.ui-ct__text { margin: 8px 0 0; font-size: 14px; line-height: 21px; overflow-wrap: anywhere; white-space: pre-line; text-align: start; color: var(--ui-ct-text); }\n.ui-ct__command { color: var(--ui-ct-muted); }\n\n.ui-ct__status { margin-top: 8px; }\n.ui-ct__status-btn {\n  display: inline-flex;\n  align-items: center;\n  gap: 7px;\n  max-width: 100%;\n  height: 26px;\n  padding: 0 6px 0 8px;\n  border: 0;\n  border-radius: calc(var(--aui-radius-sm, 7px) + 1px);\n  background: transparent;\n  font-size: 14px !important;\n  transition: background-color 140ms ease;\n}\n/* The global button reset sets margin: 0 – shift the row so the check icon sits centered under the avatars */\n.ui-ct .ui-ct__status-btn { margin-left: -4px; }\n.ui-ct__status-btn:hover:not(:disabled) { background: var(--ui-ct-row-hover); }\n.ui-ct__status-btn:disabled { cursor: default; }\n.ui-ct__status-text { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }\n.ui-ct__check, .ui-ct__chevron { flex: none; }\n.ui-ct__check {\n  display: grid;\n  place-items: center;\n  width: 16px;\n  height: 16px;\n  border-radius: 50%;\n  background: var(--ui-ct-ok);\n  color: #fff;\n}\n.ui-ct__chevron { display: grid; color: var(--ui-ct-muted); transition: transform 260ms var(--ui-ct-ease); }\n.ui-ct__status-btn[aria-expanded=\"true\"] .ui-ct__chevron { transform: rotate(180deg); }\n.ui-ct__details {\n  display: grid;\n  grid-template-rows: 0fr;\n  transition: grid-template-rows 320ms var(--ui-ct-ease);\n}\n.ui-ct__details[data-open] { grid-template-rows: 1fr; }\n.ui-ct__details ul {\n  min-height: 0;\n  overflow: hidden;\n  margin: 0;\n  padding: 0 0 0 28px;\n  list-style: none;\n}\n.ui-ct__details li {\n  position: relative;\n  margin-top: 6px;\n  font-size: 13px;\n  line-height: 19px;\n  overflow-wrap: anywhere;\n  text-align: start;\n  color: var(--ui-ct-muted);\n  /* Closing: lines fade out quickly while the box folds */\n  opacity: 0;\n  transform: translateY(-4px);\n  transition: opacity 160ms ease, transform 220ms var(--ui-ct-ease);\n}\n/* Opening: lines come in one after another */\n.ui-ct__details[data-open] li {\n  opacity: 1;\n  transform: none;\n  transition-duration: 320ms, 420ms;\n  transition-delay: calc(60ms + var(--i, 0) * 60ms);\n}\n/* Tree lines instead of dots: each line gets its own corner – down on the axis of the check icon, then a rounded turn right */\n.ui-ct__details li:first-child { margin-top: 5px; }\n.ui-ct__details li::before {\n  content: \"\";\n  position: absolute;\n  left: -16.625px;\n  top: -3px;\n  width: 10.5px;\n  height: 13px;\n  border-left: 1.25px solid var(--ui-ct-dot);\n  border-bottom: 1.25px solid var(--ui-ct-dot);\n  border-bottom-left-radius: 5px;\n}\n/* The first branch starts with a small gap under the check icon */\n.ui-ct__details li:first-child::before {\n  top: -5px;\n  height: 15px;\n}\n\n.ui-ct__thinking {\n  display: inline-block;\n  margin: 8px 0 0;\n  font-size: 14px;\n  background: linear-gradient(90deg, var(--ui-ct-subtle) 0%, var(--ui-ct-subtle) 35%, rgba(255, 255, 255, 0.9) 50%, var(--ui-ct-subtle) 65%, var(--ui-ct-subtle) 100%);\n  background-size: 300% 100%;\n  -webkit-background-clip: text;\n  background-clip: text;\n  -webkit-text-fill-color: transparent;\n  animation: ui-ct-shine 1.6s linear infinite;\n}\n\n.ui-ct__composer {\n  display: flex;\n  align-items: center;\n  gap: 10px;\n  padding: 9px 9px 9px 18px;\n}\n.ui-ct__input {\n  flex: 1;\n  min-width: 0;\n  height: 32px;\n  border: 0;\n  outline: none;\n  background: transparent;\n  font: inherit;\n  font-size: 14px;\n  color: var(--ui-ct-ink);\n}\n.ui-ct__input::placeholder { color: var(--ui-ct-subtle); }\n.ui-ct__send {\n  display: grid;\n  place-items: center;\n  flex: none;\n  width: 30px;\n  height: 30px;\n  padding: 0;\n  border: 0;\n  border-radius: 50%;\n  background: linear-gradient(#323137, #201e25);\n  box-shadow: 0 0 0 1px #0d0d0d, 0 2px 4px rgba(0, 0, 0, 0.1);\n  color: #fff !important;\n  transition: opacity 160ms ease, transform 160ms ease;\n}\n.ui-ct__send:disabled { opacity: 0.3; cursor: default; }\n.ui-ct__send:not(:disabled):active { transform: scale(0.94); }\n\n@keyframes ui-ct-in { from { opacity: 0; transform: translateY(4px); } }\n@keyframes ui-ct-shine { from { background-position: 100% 0; } to { background-position: 0% 0; } }\n@media (prefers-reduced-motion: reduce) {\n  .ui-ct__msg > *, .ui-ct__thinking { animation: none; }\n  .ui-ct__details, .ui-ct__details li, .ui-ct__chevron { transition: none; }\n}\n\n/* Height changes glide instead of jumping */\n.ui-ct__morph { overflow: hidden; }\n.ui-ct__morph[data-smooth] { transition: height 380ms var(--aui-ease, cubic-bezier(0.22, 1, 0.36, 1)); }\n@media (prefers-reduced-motion: reduce) { .ui-ct__morph[data-smooth] { transition: none; } }\n\n\n/* Text fields: no focus box while typing – also against global :focus-visible rules of the host page */\n.ui-ct input:not([type=\"checkbox\"]):not([type=\"radio\"]):focus-visible,\n.ui-ct textarea:focus-visible,\n.ui-ct [contenteditable]:focus-visible { outline: none; }\n/* Dark mode: follows a .dark class or data-theme=\"dark\" on any ancestor, e.g. <html> */\n:where(.dark, [data-theme=\"dark\"]) .ui-ct {\n  --ui-ct-focus: var(--aui-focus, rgba(77, 141, 255, 0.8));\n  --ui-ct-tray: var(--aui-subtle, #161618);\n  --ui-ct-card: var(--aui-surface, #232326);\n  --ui-ct-ink: var(--aui-ink, #ededed);\n  --ui-ct-text: var(--aui-ink, #c4c4c4);\n  --ui-ct-muted: var(--aui-muted, #8f8f8f);\n  --ui-ct-ok: #1e8a4f;\n  --ui-ct-accent-text: var(--aui-info, #4fb0fe);\n  --ui-ct-border: var(--aui-border, rgba(255, 255, 255, 0.08));\n  --ui-ct-shadow: 0 1px 2px rgba(0, 0, 0, 0.4);\n  --ui-ct-hover: var(--aui-subtle, rgba(255, 255, 255, 0.06));\n  --ui-ct-row-hover: var(--aui-subtle, rgba(255, 255, 255, 0.06));\n  --ui-ct-initials: color-mix(in srgb, var(--aui-blue, #4fb0fe) 16%, transparent);\n  --ui-ct-dot: rgba(255, 255, 255, 0.14);\n  --ui-ct-subtle: var(--aui-placeholder, #6b6b70);\n  --ui-ct-avatar-ring: rgba(255, 255, 255, 0.08);\n}\n:where(.dark, [data-theme=\"dark\"]) .ui-ct__send {\n  background: linear-gradient(#f4f4f5, #e4e4e7);\n  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.6), 0 2px 4px rgba(0, 0, 0, 0.35), inset 0 1px 0 #ffffff;\n  color: #121213 !important;\n}\n`;\n"}]}