\ProvidesPackage{bussproofs-colorful}[2026/01/27 Color extension for bussproof]
% bussproofs-colorful.sty Version 1.0
% Color extension for the bussproofs package.
% Copyright (C) 2026 by Julian (lambdaphoenix)
% 
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3c
% of this license or (at your option) any later version.
% The latest version of this license is in
%   https://www.latex-project.org/lppl.txt
% and version 1.3c or later is part of all distributions of LaTeX
% version 2008 or later.
%
% This work has the LPPL maintenance status `maintained'.
% 
% The Current Maintainer of this work is Julian.
%
% This work consists of the file bussproofs-colorful.sty.
% 
% This package depends on:
% - bussproofs
% - xcolor
% - kvoptions
%
% This package adds color support to proof trees created with
% the bussproofs package. It provides user-level control over:
% - node (formula) colors
% - inference line colors
% - rule label colors
%
% Features:
% - Package options:
%      nodecolor=<color>
%       linecolor=<color>
%       labelcolor=<color>
%      theme=<name>
%      patchnodes=true/false
%      patchlines=true/false
%      patchlabels=true/false
%      debug=true/false
% - Built-in themes:
%      classic, dark, pastel, highcontrast
% - Runtime color control:
%      \SetNodeColor{<color>}
%      \SetLineColor{<color>}
%      \SetLabelColor{<color>}
%      \LoadProofTheme{<theme>}
%      \ResetProofColors
% - Local color blocks:
%      \begin{ProofColors}[node=red, line=blue]
%          ...
%      \end{ProofColors}
% - Per-environment color scoping for prooftree environments.
%
% Usage example:
%   \usepackage[nodecolor=red, linecolor=blue]{bussproofs-colorful}
%
%   \begin{prooftree}
%       \SetNodeColor{orange}
%       \AxiomC{A}
%       \SetLabelColor{green}
%       \RightLabel{R}
%       \UnaryInfC{B}
%   \end{prooftree}
%
% Implementation notes:
% The patching strategy follows a minimal-invasion approach:
% most patched macros are direct copies of the corresponding
% bussproofs definitions, with only color insertion points added.
% No structural changes are made to the original layout logic,
% box construction, or spacing algorithms. This ensures full
% compatibility with bussproofs while enabling color customization.
% --------------------------------------------------------------------

\RequirePackage{bussproofs}
\RequirePackage{xcolor}
\RequirePackage{kvoptions}

% --------------------------------------------------------------------
% Package options (key=value)
% --------------------------------------------------------------------
\SetupKeyvalOptions{
  family=bpcolor,
  prefix=bpcolor@
}

% Color options
\DeclareStringOption{nodecolor}
\DeclareStringOption{linecolor}
\DeclareStringOption{labelcolor}

% Feature toggles
\DeclareBoolOption[true]{patchnodes}
\DeclareBoolOption[true]{patchlines}
\DeclareBoolOption[true]{patchlabels}

% Modes
\DeclareBoolOption{debug}

% Theme option
\DeclareStringOption{theme}

\ProcessKeyvalOptions*

% --------------------------------------------------------------------
% Defaults
% --------------------------------------------------------------------
\ifx\bpcolor@nodecolor\@empty
    \renewcommand{\bpcolor@nodecolor}{black}
\fi
    \ifx\bpcolor@linecolor\@empty
    \renewcommand{\bpcolor@linecolor}{black}
\fi
\ifx\bpcolor@labelcolor\@empty
    \renewcommand{\bpcolor@labelcolor}{black}
\fi

% --------------------------------------------------------------------
% Internal color variables (initialized from options)
% --------------------------------------------------------------------
\newcommand{\bpnodecolor}{\bpcolor@nodecolor}
\newcommand{\bplinerulecolor}{\bpcolor@linecolor}
\newcommand{\bplabelcolor}{\bpcolor@labelcolor}

% --------------------------------------------------------------------
% Public setters (runtime color changes)
% --------------------------------------------------------------------
\newcommand{\SetNodeColor}[1]{\renewcommand{\bpnodecolor}{#1}}
\newcommand{\SetLineColor}[1]{\renewcommand{\bplinerulecolor}{#1}}
\newcommand{\SetLabelColor}[1]{\renewcommand{\bplabelcolor}{#1}}

% Reset to package defaults
\newcommand{\ResetProofColors}{%
    \renewcommand{\bpnodecolor}{\bpcolor@nodecolor}%
    \renewcommand{\bplinerulecolor}{\bpcolor@linecolor}%
    \renewcommand{\bplabelcolor}{\bpcolor@labelcolor}%
}

% --------------------------------------------------------------------
% Theme system
% --------------------------------------------------------------------
% Classic
\def\bp@theme@classic@node{black}
\def\bp@theme@classic@line{black}
\def\bp@theme@classic@label{black}

% Dark
\def\bp@theme@dark@node{white}
\def\bp@theme@dark@line{gray}
\def\bp@theme@dark@label{yellow}

% Pastel
\def\bp@theme@pastel@node{blue!60}
\def\bp@theme@pastel@line{purple!50}
\def\bp@theme@pastel@label{teal!60}

% High contrast
\def\bp@theme@highcontrast@node{black}
\def\bp@theme@highcontrast@line{red}
\def\bp@theme@highcontrast@label{blue}

% Set as defaults
\def\bp@applytheme@defaults#1{%
    \def\bpcolor@nodecolor{\csname bp@theme@#1@node\endcsname}%
    \def\bpcolor@linecolor{\csname bp@theme@#1@line\endcsname}%
    \def\bpcolor@labelcolor{\csname bp@theme@#1@label\endcsname}%
    \ResetProofColors%
}

% Set at runtime
\def\bp@applytheme@runtime#1{%
    \SetNodeColor{\csname bp@theme@#1@node\endcsname}%
    \SetLineColor{\csname bp@theme@#1@line\endcsname}%
    \SetLabelColor{\csname bp@theme@#1@label\endcsname}%
}

% Load theme
\def\LoadProofTheme#1{%
    \bp@applytheme@runtime{#1}%
}

% Apply theme at package load
\ifx\bpcolor@theme\@empty\else%
    \bp@applytheme@defaults{\bpcolor@theme}%
\fi


% --------------------------------------------------------------------
% Debug helper
% --------------------------------------------------------------------
\newcommand{\bp@debug}[1]{%
    \ifbpcolor@debug
        \PackageInfo{bussproofs-colorful}{#1}%
    \fi
}

% --------------------------------------------------------------------
% Local color block environment
% --------------------------------------------------------------------
\NewDocumentEnvironment{ProofColors}{O{}}
{
    \begingroup
    \kvsetkeys{bpcolor/local}{#1}%
}
{
    \endgroup
}

\kv@set@family@handler{bpcolor/local}{%
    \csname bpcolor@set@#1\endcsname{#2}%
}

\def\bpcolor@set@node#1{\renewcommand{\bpcolor@nodecolor}{#1}}
\def\bpcolor@set@line#1{\renewcommand{\bpcolor@linecolor}{#1}}
\def\bpcolor@set@label#1{\renewcommand{\bpcolor@labelcolor}{#1}}
\def\bpcolor@set@theme#1{\bp@applytheme@defaults{#1}}

% --------------------------------------------------------------------
% Patches (only applied if toggles enabled)
% --------------------------------------------------------------------

% --- Inference line -------------------------------------------------
\ifbpcolor@patchlines
\bp@debug{Patching inference lines}
\def\buildSingleScore{% Make an hbox with a single score.
    \displace=\curScoreEnd%
    \advance \displace by -\curScoreStart%
    \global\setbox \myBoxD =%
        \hbox to \displace{%
            {%
                \color{\bplinerulecolor}%
                \expandafter\xleaders\theScoreFiller\hfill%
            }%
        }%
}
\fi

% --- Labels ---------------------------------------------------------
\ifbpcolor@patchlabels
\bp@debug{Patching labels}
\def\LeftLabel#1{%
    \global\setbox\myBoxLL=\hbox{{\textcolor{\bplabelcolor}{#1}}\hskip\labelSpacing}%
    \ignorespaces
}
\def\RightLabel#1{%
    \global\setbox\myBoxRL=\hbox{\hskip\labelSpacing {\textcolor{\bplabelcolor}{#1}}}%
    \ignorespaces
}
\fi

% --- Nodes ----------------------------------------------------------
\ifbpcolor@patchnodes
\bp@debug{Patching nodes}
\def\Axiom$#1\fCenter#2${%
    % Get level and correct names set.
    \prepAxiom%
    % Define the boxes
    \setbox\myBoxA=\hbox{$\mathord{\textcolor{\bpnodecolor}{#1}}\fCenter\mathord{\relax}$}%
    \setbox\myBoxB=\hbox{$\textcolor{\bpnodecolor}{#2}$}%
    \global\setbox\curBox=%
         \hbox{\hskip\ScoreOverhangLeft\relax%
        \unhcopy\myBoxA\unhcopy\myBoxB\hskip\ScoreOverhangRight\relax}%
    % Set the relevant dimensions for the boxes
    \global\curScoreStart=0pt \relax
    \global\curScoreEnd=\wd\curBox \relax
    \global\curCenter=\wd\myBoxA \relax
    \global\advance \curCenter by \ScoreOverhangLeft%
    \ignorespaces
}

\def\AxiomC#1{      % Note argument not in math mode
    % Get level and correct names set.
    \prepAxiom%
        % Define the box.
    \setbox\myBoxA=\hbox{\textcolor{\bpnodecolor}{#1}}%
    \global\setbox\curBox =%
        \hbox{\hskip\ScoreOverhangLeft\relax%
                        \unhcopy\myBoxA\hskip\ScoreOverhangRight\relax}%
    % Set the relevant dimensions for the boxes
        \global\curScoreStart=0pt \relax
        \global\curScoreEnd=\wd\curBox \relax
        \global\curCenter=.5\wd\curBox \relax
        \global\advance \curCenter by \ScoreOverhangLeft%
    \ignorespaces
}

\def\buildConclusion#1#2{% Build lower sequent w/ center at \fCenter position.
    % Define the boxes
        \setbox\myBoxA=\hbox{$\mathord{\textcolor{\bpnodecolor}{#1}}\fCenter\mathord{\relax}$}%
        \setbox\myBoxB=\hbox{$\textcolor{\bpnodecolor}{#2}$}%
    % Put them together in \myBoxC
    \setbox\myBoxC =%
          \hbox{\hskip\ScoreOverhangLeft\relax%
        \unhcopy\myBoxA\unhcopy\myBoxB\hskip\ScoreOverhangRight\relax}%
    % Calculate the center of the \myBoxC string.
    \newScoreStart=0pt \relax%
    \newCenter=\wd\myBoxA \relax%
    \advance \newCenter by \ScoreOverhangLeft%
    \newScoreEnd=\wd\myBoxC%
}

\def\buildConclusionC#1{% Build lower sequent w/o \fCenter present.
        % Define the box.
    \setbox\myBoxA=\hbox{\textcolor{\bpnodecolor}{#1}}%
    \setbox\myBoxC =%
        \hbox{\hbox{\hskip\ScoreOverhangLeft\relax%
                        \unhcopy\myBoxA\hskip\ScoreOverhangRight\relax}}%
    % Calculate kerning to line up centers
    \newScoreStart=0pt \relax%
    \newCenter=.5\wd\myBoxC \relax%
    \newScoreEnd=\wd\myBoxC%
        \advance \newCenter by \ScoreOverhangLeft%
}
\fi

% --------------------------------------------------------------------
% Version macro
% --------------------------------------------------------------------
\newcommand{\bussproofscolorfulVersion}{1.0}