%% chatui.sty
%% A LaTeX package for typesetting AI chat transcripts, reasoning/thinking
%% traces, tool-call traces, and attachments, styled as terminal, web, or
%% desktop chat UIs.
%%
%% Author: Nilesh Verma <me@nileshverma.com>
%% License: LPPL 1.3c
%% See chatui-doc.pdf for the full manual.
%%
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{chatui}[2026/08/21 v1.0.0 Chat UI, reasoning trace, tool-call trace, and attachment boxes]

\RequirePackage{etoolbox}
\RequirePackage{xparse}
\RequirePackage{kvoptions}
\RequirePackage{xcolor}
\RequirePackage[most]{tcolorbox}
\RequirePackage{tikz}
\usetikzlibrary{shadows}
\RequirePackage{amssymb}
\RequirePackage{pifont}
\RequirePackage{graphicx}

%% -----------------------------------------------------------------------
%% Font hooks: every box below uses these two macros instead of a literal
%% \sffamily / \ttfamily, so \renewcommand{\chatuiFontSans}{...} (or Mono)
%% after \usepackage swaps the font package-wide. Redefine BEFORE the first
%% chatui environment in the document, e.g.:
%%   \usepackage{inconsolata}
%%   \renewcommand{\chatuiFontMono}{\ttfamily}  % inconsolata redefines \ttfamily
%%   \renewcommand{\chatuiFontSans}{\fontfamily{qhv}\selectfont}
%% -----------------------------------------------------------------------
\newcommand{\chatuiFontSans}{\sffamily}
\newcommand{\chatuiFontMono}{\ttfamily}

%% -----------------------------------------------------------------------
%% Package options: style = terminal | web | desktop, theme = light | dark
%% -----------------------------------------------------------------------
\SetupKeyvalOptions{family=chatui, prefix=chatui@}
\DeclareStringOption[web]{style}
\DeclareStringOption[auto]{theme}
\ProcessKeyvalOptions*

\newbool{chatui@isterminal}
\newbool{chatui@isweb}
\newbool{chatui@isdesktop}
\newbool{chatui@isdark}

\ifdefstring{\chatui@style}{terminal}{\booltrue{chatui@isterminal}}{}
\ifdefstring{\chatui@style}{web}{\booltrue{chatui@isweb}}{}
\ifdefstring{\chatui@style}{desktop}{\booltrue{chatui@isdesktop}}{}
%% theme=auto (default): terminal defaults to dark, web/desktop default to
%% light. theme=light / theme=dark override that regardless of style.
\ifdefstring{\chatui@theme}{dark}{\booltrue{chatui@isdark}}{}
\ifdefstring{\chatui@theme}{auto}{\ifbool{chatui@isterminal}{\booltrue{chatui@isdark}}{}}{}

\ifbool{chatui@isterminal}{}{\ifbool{chatui@isweb}{}{\ifbool{chatui@isdesktop}{%
}{\booltrue{chatui@isweb}}}} % fall back to web if style is unrecognised

%% -----------------------------------------------------------------------
%% Palette: users may \colorlet{chatuiUserBg}{...} etc. after loading
%% -----------------------------------------------------------------------
\definecolor{chatuiUserBg}{HTML}{2F81F7}
\definecolor{chatuiUserFg}{HTML}{FFFFFF}
\definecolor{chatuiAssistantBg}{HTML}{F0F1F3}
\definecolor{chatuiAssistantFg}{HTML}{1A1A1A}
\colorlet{chatuiAssistantBorder}{chatuiAssistantBg}
\definecolor{chatuiThinkBg}{HTML}{F5F7F8}
\definecolor{chatuiThinkBorder}{HTML}{C7CDD3}
\definecolor{chatuiThinkFg}{HTML}{55606A}
\definecolor{chatuiToolBg}{HTML}{FAFAF9}
\definecolor{chatuiToolBorder}{HTML}{D8DEE4}
\definecolor{chatuiToolAccent}{HTML}{7C5CFC}
\definecolor{chatuiOk}{HTML}{2E9E5B}
\definecolor{chatuiErr}{HTML}{D64545}
\definecolor{chatuiWarn}{HTML}{C8871E}
\definecolor{chatuiWindowChrome}{HTML}{E4E6E9}
%% App-window chrome (web/desktop styles): light defaults, dark overrides below
\colorlet{chatuiAppBg}{white}
\colorlet{chatuiAppText}{black}
\colorlet{chatuiAppChrome}{chatuiWindowChrome}
\colorlet{chatuiAppChromeText}{black!55}
\colorlet{chatuiAppBorder}{chatuiWindowChrome!60!black}
\colorlet{chatuiAppPillBg}{white}
\colorlet{chatuiAppPillBorder}{chatuiWindowChrome!80!black}
\colorlet{chatuiAppPillText}{black!55}
\definecolor{chatuiTermBg}{HTML}{101418}
\definecolor{chatuiTermFg}{HTML}{D7DEE4}
\definecolor{chatuiTermAccent}{HTML}{63E6A5}
\definecolor{chatuiTermUser}{HTML}{63C7FF}
\definecolor{chatuiTermThinkBg}{HTML}{1B2129}
\definecolor{chatuiTermThinkBorder}{HTML}{2E3947}
\definecolor{chatuiTermThinkFg}{HTML}{9FADBA}
\definecolor{chatuiTermToolBg}{HTML}{161B22}
\definecolor{chatuiTermToolBorder}{HTML}{30363D}
\definecolor{chatuiTermToolAccent}{HTML}{9D8CFF}
\colorlet{chatuiTermBarFill}{black!70}
\colorlet{chatuiTermBarText}{chatuiTermFg!70!white}
\newcommand{\chatuiTermWindowRule}{0pt}
\colorlet{chatuiTermWindowBorder}{chatuiTermBg}

%% Light-terminal palette (used when style=terminal, theme=light)
\definecolor{chatuiTermBgLight}{HTML}{FFFFFF}
\definecolor{chatuiTermFgLight}{HTML}{1F2328}
\definecolor{chatuiTermAccentLight}{HTML}{1B7F4C}
\definecolor{chatuiTermUserLight}{HTML}{1B5FBF}
\definecolor{chatuiTermThinkBgLight}{HTML}{F5F7F8}
\definecolor{chatuiTermThinkBorderLight}{HTML}{C7CDD3}
\definecolor{chatuiTermThinkFgLight}{HTML}{55606A}
\definecolor{chatuiTermToolBgLight}{HTML}{FAFAF9}
\definecolor{chatuiTermToolBorderLight}{HTML}{D8DEE4}
\definecolor{chatuiTermToolAccentLight}{HTML}{7C5CFC}

%% Dark theme reuses the exact terminal-dark palette for every style, so
%% web/desktop/terminal all look like the same "dark mode" instead of each
%% style inventing its own dark colors.
\ifbool{chatui@isdark}{%
  \colorlet{chatuiAssistantBg}{chatuiTermBg!80!white}
  \colorlet{chatuiAssistantFg}{chatuiTermFg}
  \colorlet{chatuiAssistantBorder}{gray!30}
  \colorlet{chatuiThinkBg}{chatuiTermThinkBg}
  \colorlet{chatuiThinkBorder}{chatuiTermThinkBorder}
  \colorlet{chatuiThinkFg}{chatuiTermThinkFg}
  \colorlet{chatuiToolBg}{chatuiTermToolBg}
  \colorlet{chatuiToolBorder}{chatuiTermToolBorder}
  \colorlet{chatuiToolAccent}{chatuiTermToolAccent}
  \colorlet{chatuiAppBg}{chatuiTermBg}
  \colorlet{chatuiAppText}{chatuiTermFg}
  \colorlet{chatuiAppChrome}{chatuiTermBarFill}
  \colorlet{chatuiAppChromeText}{chatuiTermBarText}
  \colorlet{chatuiAppPillBg}{chatuiTermToolBg}
  \colorlet{chatuiAppPillBorder}{chatuiTermToolBorder}
  \colorlet{chatuiAppPillText}{chatuiTermBarText}
}{%
  \colorlet{chatuiTermBg}{chatuiTermBgLight}
  \colorlet{chatuiTermFg}{chatuiTermFgLight}
  \colorlet{chatuiTermAccent}{chatuiTermAccentLight}
  \colorlet{chatuiTermUser}{chatuiTermUserLight}
  \colorlet{chatuiTermThinkBg}{chatuiTermThinkBgLight}
  \colorlet{chatuiTermThinkBorder}{chatuiTermThinkBorderLight}
  \colorlet{chatuiTermThinkFg}{chatuiTermThinkFgLight}
  \colorlet{chatuiTermToolBg}{chatuiTermToolBgLight}
  \colorlet{chatuiTermToolBorder}{chatuiTermToolBorderLight}
  \colorlet{chatuiTermToolAccent}{chatuiTermToolAccentLight}
  \colorlet{chatuiTermBarFill}{chatuiWindowChrome}
  \colorlet{chatuiTermBarText}{black!55}
  \renewcommand{\chatuiTermWindowRule}{0.7pt}
  \colorlet{chatuiTermWindowBorder}{black!35}
}

%% -----------------------------------------------------------------------
%% Window chrome (terminal / browser / desktop title bars)
%% -----------------------------------------------------------------------
\newcommand{\chatui@dots}[3]{%
  \begin{tikzpicture}[baseline=-0.5ex]
    \foreach \x/\c in {0/#1,0.35/#2,0.7/#3}{%
      \fill[\c] (\x,0) circle (0.06);
    }
  \end{tikzpicture}%
}

%% All three window-chrome boxes use tcolorbox's native title area for the
%% bar (colbacktitle) instead of a hand-drawn overlay rectangle: the title
%% area shares the box's own rounded-corner path, so it never seams against
%% the frame the way an independently-rounded overlay node can.
\newtcolorbox{chatui@windowbox}[2][]{%
  enhanced, breakable, colback=chatuiAppBg, coltext=chatuiAppText,
  boxrule=\chatuiTermWindowRule, colframe=chatuiTermWindowBorder,
  colbacktitle=chatuiAppChrome, coltitle=chatuiAppChromeText,
  arc=3mm, left=4mm, right=4mm, bottom=4mm,
  toptitle=2.6mm, bottomtitle=2.6mm, halign title=center,
  fonttitle=\small\chatuiFontSans,
  title={#2},
  overlay={%
    \ifnum\value{tcbbreakpart}=1
      \node[anchor=west, xshift=2mm] at (title.west)
        {\chatui@dots{red!70!black}{orange!80!yellow}{green!60!black}};
    \fi
  },
  #1
}

\newtcolorbox{chatui@browserbox}[2][]{%
  enhanced, breakable, colback=chatuiAppBg, coltext=chatuiAppText,
  boxrule=\chatuiTermWindowRule, colframe=chatuiTermWindowBorder,
  colbacktitle=chatuiAppChrome,
  arc=2mm, left=4mm, right=4mm, bottom=4mm,
  toptitle=2.4mm, bottomtitle=2.4mm,
  fonttitle=\scriptsize\chatuiFontMono,
  title={\phantom{Xg}},
  overlay={%
    \ifnum\value{tcbbreakpart}=1
      \node[anchor=west, xshift=2mm] at (title.west)
        {\chatui@dots{red!70!black}{orange!80!yellow}{green!60!black}};
      \node[fill=chatuiAppPillBg, draw=chatuiAppPillBorder, rounded corners=2mm,
            minimum width=0.5\linewidth, minimum height=3.6mm,
            font=\scriptsize\chatuiFontMono, text=chatuiAppPillText] at (title.center) {#2};
    \fi
  },
  #1
}

\newtcolorbox{chatui@termbox}[2][]{%
  enhanced, breakable, colback=chatuiTermBg, coltext=chatuiTermFg,
  boxrule=\chatuiTermWindowRule, colframe=chatuiTermWindowBorder,
  colbacktitle=chatuiTermBarFill, coltitle=chatuiTermBarText,
  arc=2mm, left=4mm, right=4mm, bottom=4mm,
  toptitle=2.4mm, bottomtitle=2.4mm, halign title=center,
  fonttitle=\scriptsize\chatuiFontMono,
  title={#2},
  fontupper=\chatuiFontMono\small,
  overlay={%
    \ifnum\value{tcbbreakpart}=1
      \node[anchor=west, xshift=2mm] at (title.west)
        {\chatui@dots{red!70!black}{orange!80!yellow}{green!60!black}};
    \fi
  },
  #1
}

%% chatconversation: outer window that frames a whole transcript
\newenvironment{chatconversation}[1][chatui]{%
  \ifbool{chatui@isterminal}{\begin{chatui@termbox}{#1}}{}%
  \ifbool{chatui@isweb}{\begin{chatui@browserbox}{#1}}{}%
  \ifbool{chatui@isdesktop}{\begin{chatui@windowbox}{#1}}{}%
}{%
  \ifbool{chatui@isterminal}{\end{chatui@termbox}}{}%
  \ifbool{chatui@isweb}{\end{chatui@browserbox}}{}%
  \ifbool{chatui@isdesktop}{\end{chatui@windowbox}}{}%
}

%% -----------------------------------------------------------------------
%% Chat bubbles: chatuser / chatassistant
%% -----------------------------------------------------------------------
\newtcolorbox{chatui@bubbleuser}{%
  enhanced, colback=chatuiUserBg, colframe=chatuiUserBg,
  coltext=chatuiUserFg, arc=3mm, boxrule=0pt,
  left=3mm, right=3mm, top=1.6mm, bottom=1.6mm,
  width=0.78\linewidth, halign=left,
  fontupper=\chatuiFontSans\small,
  drop shadow={opacity=0.12, shadow xshift=0pt, shadow yshift=-1pt}
}
\newtcolorbox{chatui@bubbleassistant}{%
  enhanced, colback=chatuiAssistantBg, colframe=chatuiAssistantBorder,
  coltext=chatuiAssistantFg, arc=3mm, boxrule=0.4pt,
  left=3mm, right=3mm, top=1.6mm, bottom=1.6mm,
  width=0.78\linewidth, halign=left,
  fontupper=\chatuiFontSans\small,
  drop shadow={opacity=0.08, shadow xshift=0pt, shadow yshift=-1pt}
}

%% chatuser/chatassistant used to wrap their bubble in a \minipage to align
%% it left/right, but minipages can never break across a page, so a long
%% bubble that overflowed the page dragged the whole enclosing breakable
%% window down with it and corrupted the chrome on the continuation page.
%% flushright/flushleft are list-based (like itemize), not a single boxed
%% unit, so the inner breakable tcolorbox is still free to split normally.
\newenvironment{chatuser}[1][user]{%
  \ifbool{chatui@isterminal}{%
    \par\noindent\chatuiFontMono\small\color{chatuiTermFg}%
    \textcolor{chatuiTermUser}{#1>}\space%
  }{%
    \begin{flushright}
    \begin{chatui@bubbleuser}%
  }%
}{%
  \ifbool{chatui@isterminal}{%
    \par\vspace{2mm}%
  }{%
    \end{chatui@bubbleuser}%
    \end{flushright}%
  }%
}

\newenvironment{chatassistant}[1][Assistant]{%
  \ifbool{chatui@isterminal}{%
    \par\noindent\chatuiFontMono\small\color{chatuiTermFg}%
    \textcolor{chatuiTermAccent}{#1>}\space%
  }{%
    \noindent
    \begin{chatui@bubbleassistant}%
  }%
}{%
  \ifbool{chatui@isterminal}{%
    \par\vspace{2mm}%
  }{%
    \end{chatui@bubbleassistant}\par\vspace{2mm}%
  }%
}

%% -----------------------------------------------------------------------
%% Reasoning / thinking trace
%% mode = steps (default, arrow-prefixed \tstep bullets) | paragraph (plain
%% upright prose, easier to read for long reasoning blocks than italics).
%% -----------------------------------------------------------------------
\newtcolorbox{chatui@think@light}[2][]{%
  enhanced, colback=chatuiThinkBg, colframe=chatuiThinkBorder,
  coltext=chatuiThinkFg, arc=2mm, boxrule=0.4pt,
  fonttitle=\scriptsize\chatuiFontSans\bfseries, coltitle=chatuiThinkFg,
  title={\raisebox{-0.15ex}{$\rightsquigarrow$}\ #2},
  fontupper=\itshape\chatuiFontSans\small,
  left=3mm, right=3mm, top=1.5mm, bottom=1.5mm,
  boxsep=1mm, top=2mm,
  #1
}
\newtcolorbox{chatui@think@dark}[2][]{%
  enhanced, colback=chatuiTermThinkBg, colframe=chatuiTermThinkBorder,
  coltext=chatuiTermThinkFg, arc=2mm, boxrule=0.4pt,
  fonttitle=\scriptsize\chatuiFontMono\bfseries, coltitle=chatuiTermAccent,
  title={\raisebox{-0.15ex}{$\rightsquigarrow$}\ #2},
  fontupper=\itshape\chatuiFontMono\small,
  left=3mm, right=3mm, top=1.5mm, bottom=1.5mm,
  boxsep=1mm, top=2mm,
  #1
}
\NewDocumentEnvironment{chatthinking}{O{Reasoning} O{steps}}{%
  \ifstrequal{#2}{paragraph}{%
    \ifbool{chatui@isterminal}{\begin{chatui@think@dark}[fontupper=\upshape\chatuiFontMono\small]{#1}}%
                               {\begin{chatui@think@light}[fontupper=\upshape\chatuiFontSans\small]{#1}}%
  }{%
    \ifbool{chatui@isterminal}{\begin{chatui@think@dark}{#1}}%
                               {\begin{chatui@think@light}{#1}}%
  }%
}{%
  \ifbool{chatui@isterminal}{\end{chatui@think@dark}}{\end{chatui@think@light}}%
}
\newcommand{\tstep}[1]{\par\noindent{\upshape$\rightarrow$}~#1\par}

%% -----------------------------------------------------------------------
%% Tool-call trace: chattool[status][kind]{tool name}
%% kind = api (default, "tool: name" chip) | cli (shell-style "$ name")
%%      | code (function-call style "</> name")
%% -----------------------------------------------------------------------
\newcommand{\chatui@tool@label}[3]{%
  \ifstrequal{#1}{ok}{\textcolor{#3}{\ding{51}}}{}%
  \ifstrequal{#1}{error}{\textcolor{chatuiErr}{\ding{55}}}{}%
  \ifstrequal{#1}{running}{\textcolor{chatuiWarn}{$\cdots$}}{}%
  \ %
  \ifstrequal{#2}{cli}{\textcolor{#3}{\$}\ }{}%
  \ifstrequal{#2}{code}{\textcolor{#3}{\textless/\textgreater}\ }{}%
}
\newtcolorbox{chatui@tool@light}[3]{%
  enhanced, colback=chatuiToolBg, colframe=chatuiToolBorder,
  arc=2mm, boxrule=0.5pt, left=3mm, right=3mm, top=1.5mm, bottom=1.5mm,
  fonttitle=\scriptsize\chatuiFontMono\bfseries,
  colbacktitle=chatuiToolAccent!12, coltitle=chatuiToolAccent!70!black,
  attach boxed title to top left={yshift=-2mm, xshift=3mm},
  boxed title style={boxrule=0pt, arc=1.5mm, colback=chatuiToolAccent!12},
  title={\chatui@tool@label{#1}{#2}{chatuiOk}%
         \ifstrequal{#2}{api}{tool:~#3}{#3}},
  fontupper=\chatuiFontMono\small
}
\newtcolorbox{chatui@tool@dark}[3]{%
  enhanced, colback=chatuiTermToolBg, colframe=chatuiTermToolBorder,
  coltext=chatuiTermFg, arc=2mm, boxrule=0.5pt,
  left=3mm, right=3mm, top=1.5mm, bottom=1.5mm,
  fonttitle=\scriptsize\chatuiFontMono\bfseries,
  colbacktitle=chatuiTermToolAccent!25!chatuiTermBg,
  coltitle=chatuiTermToolAccent,
  attach boxed title to top left={yshift=-2mm, xshift=3mm},
  boxed title style={boxrule=0pt, arc=1.5mm,
    colback=chatuiTermToolAccent!25!chatuiTermBg},
  title={\chatui@tool@label{#1}{#2}{chatuiTermAccent}%
         \ifstrequal{#2}{api}{tool:~#3}{#3}},
  fontupper=\chatuiFontMono\small
}
\NewDocumentEnvironment{chattool}{O{ok} O{api} m}{%
  \ifbool{chatui@isterminal}{\begin{chatui@tool@dark}{#1}{#2}{#3}}%
                             {\begin{chatui@tool@light}{#1}{#2}{#3}}%
}{%
  \ifbool{chatui@isterminal}{\end{chatui@tool@dark}}{\end{chatui@tool@light}}%
}
\newcommand{\toolargs}[1]{%
  \ifbool{chatui@isterminal}{%
    {\small\chatuiFontMono\color{chatuiTermFg!70!black}args\space\{#1\}\par}%
  }{%
    {\small\chatuiFontMono\color{chatuiAppText!65!chatuiAppBg}args\space\{#1\}\par}%
  }%
}
\newcommand{\toolresult}[1]{%
  \ifbool{chatui@isterminal}{%
    \vspace{0.5mm}{\small\chatuiFontMono\color{chatuiTermFg}result\space#1\par}%
  }{%
    \vspace{0.5mm}{\small\chatuiFontMono\color{chatuiAppText!85!chatuiAppBg}result\space#1\par}%
  }%
}

%% JSON tool-call payloads: pass raw JSON with manual \\ line breaks and
%% \quad/\hspace for indentation (LaTeX does not preserve literal whitespace).
\newtcolorbox{chatui@json@light}{%
  enhanced, colback=chatuiToolBg!55!white, boxrule=0pt,
  borderline west={1.2pt}{0pt}{chatuiToolAccent},
  left=3mm, right=2.5mm, top=1mm, bottom=1mm, boxsep=0.5mm,
  fontupper=\chatuiFontMono\scriptsize, coltext=black!75
}
\newtcolorbox{chatui@json@dark}{%
  enhanced, colback=chatuiTermToolBg!85!black, boxrule=0pt,
  borderline west={1.2pt}{0pt}{chatuiTermToolAccent},
  left=3mm, right=2.5mm, top=1mm, bottom=1mm, boxsep=0.5mm,
  fontupper=\chatuiFontMono\scriptsize, coltext=chatuiTermFg
}
\newcommand{\tooljson}[1]{%
  \vspace{0.5mm}%
  \ifbool{chatui@isterminal}{%
    \begin{chatui@json@dark}#1\end{chatui@json@dark}%
  }{%
    \begin{chatui@json@light}#1\end{chatui@json@light}%
  }%
}

%% -----------------------------------------------------------------------
%% Attachments: \chatimage[width]{path} and \chatfile{name}{size}: use
%% inside chatuser/chatassistant (or standalone) to show an image or a
%% file chip, e.g. an uploaded screenshot or an attached PDF.
%% -----------------------------------------------------------------------
\newsavebox{\chatui@imgbox}
\newcommand{\chatimage}[2][\linewidth]{%
  \par\vspace{1.5mm}\noindent
  \sbox{\chatui@imgbox}{\includegraphics[width=#1]{#2}}%
  \begin{tikzpicture}
    \clip[rounded corners=3mm] (0,0)
      rectangle (\wd\chatui@imgbox,\dimexpr\ht\chatui@imgbox+\dp\chatui@imgbox\relax);
    \node[anchor=south west, inner sep=0pt] at (0,0) {\usebox{\chatui@imgbox}};
  \end{tikzpicture}%
  \par\vspace{1mm}%
}

\newcommand{\chatui@fileicon}[1]{%
  \begin{tikzpicture}[baseline=-0.4ex, scale=0.16]
    \draw[#1, line width=0.9pt, rounded corners=0.5pt]
      (0,0) -- (0,5) -- (3,5) -- (4,4) -- (4,0) -- cycle;
    \draw[#1, line width=0.9pt] (3,5) -- (3,4) -- (4,4);
  \end{tikzpicture}%
}

\newtcolorbox{chatui@file@light}{%
  enhanced, colback=chatuiToolBg, colframe=chatuiToolBorder, boxrule=0.5pt,
  arc=2mm, left=2mm, right=3mm, top=1.2mm, bottom=1.2mm,
  fontupper=\chatuiFontMono\small, coltext=black!75
}
\newtcolorbox{chatui@file@dark}{%
  enhanced, colback=chatuiTermToolBg, colframe=chatuiTermToolBorder, boxrule=0.5pt,
  arc=2mm, left=2mm, right=3mm, top=1.2mm, bottom=1.2mm,
  fontupper=\chatuiFontMono\small, coltext=chatuiTermFg
}
\newcommand{\chatfile}[2]{%
  \par\vspace{1.5mm}\noindent
  \ifbool{chatui@isterminal}{%
    \begin{chatui@file@dark}
      \chatui@fileicon{chatuiTermToolAccent}\ \textbf{#1}%
      \ifstrequal{#2}{}{}{\ {\scriptsize\color{chatuiTermFg!70!black}(#2)}}%
    \end{chatui@file@dark}%
  }{%
    \begin{chatui@file@light}
      \chatui@fileicon{chatuiToolAccent}\ \textbf{#1}%
      \ifstrequal{#2}{}{}{\ {\scriptsize\color{black!55}(#2)}}%
    \end{chatui@file@light}%
  }%
  \par\vspace{1mm}%
}

\endinput
