\documentclass[a4paper,11pt]{article}
\usepackage[margin=22mm]{geometry}
\usepackage{xcolor}
\usepackage[tikz]{paracolrule}
\usetikzlibrary{decorations.pathmorphing}

\setlength{\parindent}{0pt}
\setlength{\parskip}{0pt}

\newcommand\AnswerItem[1]{
  \textbf{Solution #1.}
  Arrange the assumptions, transform the expression, and record the result.
  This paragraph makes the main stream long enough to cross a page boundary.
  \par
}
\newcommand\NoteItem[1]{
  \textbf{Note #1.}
  Record a warning, alternate method, or quick check in the narrow stream.
  \par
}

\begin{document}

\section*{Dashed 70:30 rule across pages}

\setlength{\columnsep}{24pt}
\setlength{\columnseprule}{1.2pt}
\columnratio{.7}
\colseprulecolor{blue!70!black}
\ParacolRuleSetup{
  style=dashed,
  dash-length=6pt,
  gap-length=3pt
}

\begin{paracol}{2}
  \ExplSyntaxOn
  \int_step_inline:nn {28}
    {
      \AnswerItem{#1}
      \int_compare:nNnT {#1} < {28} {\medskip}
    }
  \ExplSyntaxOff

  \switchcolumn[1]
  \small\raggedright\color{black!70}
  \ExplSyntaxOn
  \int_step_inline:nn {18}
    {
      \NoteItem{#1}
      \int_compare:nNnT {#1} < {18} {\medskip}
    }
  \ExplSyntaxOff
\end{paracol}

\clearpage
\section*{Arbitrary columns and styles}

\subsection*{Dotted 50:30:20 layout with per-gap colors}
\setlength{\columnsep}{20pt}
\setlength{\columnseprule}{2pt}
\columnratio{.5,.3}
\colseprulecolor{red!75!black}[0]
\colseprulecolor{blue!75!black}[1]
\ParacolRuleSetup{
  style=dotted,
  gap-length=3pt
}

\begin{paracol}{3}
  \raggedright
  \textbf{Column 0}\par
  The widest stream contains the main argument.

  \switchcolumn[1]
  \raggedright
  \textbf{Column 1}\par
  A medium stream contains an alternate method.

  \switchcolumn[2]
  \raggedright
  \textbf{Column 2}\par
  A narrow stream contains short warnings.

  \switchcolumn*[
    \subsection*{Spanning text interrupts both dotted rules}
  ]

  \raggedright
  The first stream resumes below the spanning insertion.
  \switchcolumn[1]
  \raggedright
  The second stream resumes here.
  \switchcolumn[2]
  \raggedright
  The third stream resumes here.
\end{paracol}

\subsection*{Four equal columns with a double rule}
\setlength{\columnsep}{18pt}
\setlength{\columnseprule}{2.4pt}
\columnratio{}
\normalcolseprulecolor
\ParacolRuleSetup{style=double}

\begin{paracol}{4}
  \textbf{One}\par First column.
  \switchcolumn[1]
  \textbf{Two}\par Second column.
  \switchcolumn[2]
  \textbf{Three}\par Third column.
  \switchcolumn[3]
  \textbf{Four}\par Fourth column.
\end{paracol}

\subsection*{Custom TikZ rule}
\setlength{\columnsep}{24pt}
\setlength{\columnseprule}{1pt}
\columnratio{.62}
\colseprulecolor{purple!75!black}
\ParacolRuleSetup{
  custom-line={
    \draw[
      line width=.8pt,
      decorate,
      decoration={snake,amplitude=2pt,segment length=8pt}
    ] (TOP) -- (BOT);
  }
}

\begin{paracol}{2}
  \textbf{Main stream}\par
  TikZ receives the exact top and bottom nodes of every separator segment.
  \switchcolumn
  \textbf{Commentary}\par
  Any TikZ path can connect them.
\end{paracol}

\end{document}
