% \iffalse meta-comment
%
%% File: latex-lab-sec-template.dtx
%
% Copyright (C) 2026 The LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
% license or (at your option) any later version.  The latest version
% of this license is in the file
%
%    https://www.latex-project.org/lppl.txt
%
%
% The latex-lab bundle is developed in the LaTeX2e GitHub.
% Issues may be reported at
%
%    https://github.com/latex3/latex2e/issues
%
\def\ltlabsecIIdate{2026-08-06}
\def\ltlabsecIIversion{0.9k}
%<*driver>
\DocumentMetadata{tagging=on,pdfstandard=ua-2}

\documentclass[kernel]{l3in2edoc}


\usepackage{amstext}
\usepackage{xcolor}

\EnableCrossrefs
\CodelineIndex

\usepackage{todonotes}

\begin{document}
  \DocInput{latex-lab-sec-template.dtx}
\end{document}
%</driver>
%
% \fi
%
%
% \newcommand\key[1]{\texttt{#1}}
% \newcommand\keyvalue[1]{\texttt{#1}}
%
%
% \NewDocumentCommand\fmi{sO{}m}
%   {\IfBooleanTF{#1}{\todo[inline,#2]{#3}}^^A
%                    {\todo[#2]{#3}}}
%
% \NewDocumentCommand\ufi{sO{}m}
%   {\IfBooleanTF{#1}{\todo[inline,#2]{UFi:#3}}^^A
%                    {\todo[#2]{UFi:#3}}}
%
%
% \title{Reimplementation of \LaTeXe{}'s heading commands using templates}
% \author{\LaTeX{} Project\thanks{Initial implementation by Frank Mittelbach.}}
% \date{v\ltlabsecIIversion\ \ltlabsecIIdate}
%
% \maketitle
%
%
%
% \begin{abstract}
% \end{abstract}
%
%
% \tableofcontents
% \medskip
%
%
% \begin{documentation}
%
%
%
% \section{Introduction}
%    This module reimplements tagging aware heading commands with templates.
%    The new implementation is used automatically if \cs{DocumentMetadata} is used
%    and replaces patches and redefinitions done in the \texttt{latex-lab-sec}.
%    In a later step both modules will be merged.
%
%    Most of the documentation is of interest only for class and package authors
%    who want to setup their own heading commands but the new implementation changes
%    also the user interface. This is documented first.
%
% \section{Changes to the user interface}
%
%     \subsection{New user commands}
%     \DescribeMacro\theheading
%     This command expands inside a heading to the current number.
%
%     \DescribeMacro\partmark
%     This replaces the fix \verb+\markboth{}{}+ or similar in the standard \cs{part}
%    definition.
%
%
%    \subsection{The optional argument}
%    The standard heading commands (re)defined by this module use the standard 2e syntax, e.g.,
% \begin{verbatim}
%   \section[toc]{title}
% \end{verbatim}
%    The star-form \verb+\section*{Title}+
%    stops the numbering, toc, bookmark and running header
%    as it was the way for the last 30-odd years.
%    New is that the optional argument is handled as a key/val list if an equal sign at the outer level
%    is detected, otherwise the argument is taken to be the value of the key \key{shorttitle}
%    and passed to the table of contents, the running headers, the bookmarks and used
%    with \cs{nameref}. Note that this means, that
%    \begin{verbatim}
%    \section*[Title]{Title}
%    \end{verbatim}
%    will create a toc entry and a bookmark!
%
%    The following keys can be used
%    \begin{description}
%      \item[\key{toc}] This sets the text for the table of contents. It also forces
%      that the entry is created. So
%      \begin{verbatim}
%      \section*[toc=Introduction]{Introduction to this document}
%      \end{verbatim}
%      will create an unnumbered entry \enquote{Introduction} in the table of contents.
%      An empty value (i.e., \texttt{toc=}) will suppress the toc entry.
%
%      \item[\key{running}] This sets the text for the running header and forces the
%       use of the mark command, so even with a starred section the running header will be updated.
%      An empty value will suppress the call of the mark commands, so a header from a
%      previous section will prevail.
%
%      \item[\key{bookmark}] This sets the text for the bookmarks (the PDF outline)
%      if, e.g., hyperref is loaded. As with the previous keys an empty value suppresses
%      the bookmark entry.
%
%      \item[\key{nameref}] This allows to set the text used for a cross reference
%      with \cs{nameref}.
%
%      \item[\key{label}] This sets a label, so it is an alternative to using a
%      \cs{label} command.
%
%      \item[\key{subtitle}, \key{quote}] These keys will allow to pass a subtitle and
%      a quote to the underlying code, but currently they are not yet used
%      by the implementations of the standard \LaTeX{} heading commands.
%
%      \item[\key{shorttitle}] This is the key which is used if the
%      optional argument is not of key/val form. So,
%      \begin{verbatim}
%      \section[short]{long title}
%      \end{verbatim}
%      is the same as
%      \begin{verbatim}
%      \section[shortitle=short]{long title}
%      \end{verbatim}
%      The key sets the toc, running, bookmark and nameref text. 
%      If \key{shorttitle} is used together with any of the individual keys 
%      (\key{toc}, \key{running}, \key{bookmark}, \key{nameref}) then they overwrite the default 
%      value provided by \key{shorttitle}.
%
%      \item[\key{numbered}, \key{unnumbered}] This allow to control
%      the numbering without stopping toc, running head or bookmarks as it would happen
%      with the starred version of the heading command.
%
%      \item[template keys] Any other key present is assumed to be a key that should
%      be passed to the heading instance to overwrite some of its
%      settings. So, e.g.,
%      \begin{verbatim}
%      \section[placement=top,number-format=\fbox{\theheading}]{Title}
%      \end{verbatim}
%      will force the section to start a new page and put the number into an \cs{fbox}.
%     For a list of supported keys, check the following parts of the documentation.
%    \end{description}
%
%    \subsection{Class support}
%
%    The module redefines all heading commands of the three standard
%    classes, \pkg{article}, \pkg{report} and \pkg{book}, to use the
%    new implementation.
%
%    Heading commands of other classes that are defined with
%    \cs{@startsection} are supported (with some restrictions) through
%    a compatibility layer described in the next section.
%
%    The heading commands \cs{part} and \cs{chapter} are typically
%    defined with \cs{secdef} and the internal commands \cs{@part} and
%    \cs{@chapter}. The module redefines \cs{secdef} to use the
%    standard instances for these commands---this adds tagging support
%    but \emph{changes the layout} until the class provides its own
%    instances.
%
%    Heading commands in other classes defined with \cs{secdef} will
%    likely error as the code has no real chance to know how to handle
%    such a heading.
%
%    Heading commands which use neither \cs{@startsection} nor
%    \cs{secdef} (e.g, the \cs{chapter} command of \pkg{memoir}, or
%    the heading commands of \pkg{KOMA} classes) are not changed by
%    this module and so will not be tagged correctly unless they add
%    explicit tagging support.
%
%    For the AMS-classes, \texttt{latex-lab-firstaid} contains
%    instances for \cs{part}, \cs{chapter}, \cs{section}, and all
%    other headings used by these classes. The current set of
%    instances is now assumed to reproduce the original
%    layout. Setting them up revealed a number of interesting
%    differences between these classes---not all of them intentional (I
%    think).
%
%
%
%    \subsection{Changing heading commands}\label{sec:startsection}
%
%    It is possible to change heading commands by editing the instance they use.
%    E.g., in the standard classes one could frame every heading number with
%    \begin{verbatim}
%    \EditInstance{heading}{section}
%      {number-format=\fbox{\theheading}}
%    \end{verbatim}
%    The name of the instance (here \texttt{section}) is the same as the heading command.
%
%    To support other classes which still setup their heading commands with
%    \cs{@startsection} the code has a legacy compatibility layer: the
%    \cs{@startsection} command has been redefined to setup instances on-the-fly
%    at the first use of a heading command. These instances have names using the
%    the first argument of \cs{@startsection} with an attached \texttt{-@startsection}.
%    As they are created on-the-fly these internal instances can be only edited
%    \emph{after} the first use of the heading command or by declaring (instead of editing) 
%    an instance with this name in the preamble. Also as the names of the instances
%    are built from the first argument of \cs{@startsection}
%    it is not possible to define two different heading commands
%    of the same level with \cs{@startsection} as that would require two instances with
%    different names. The next section describes how to lift this restrictions by converting
%    such sectioning commands to use the new interfaces.
%
% \subsection[label=sec:convert]{Converting heading commands defined with \cs{@startsection}}
%
% To convert a heading command defined with \cs{@startsection} to the new interface suitable
% instances must be declared. The same needs to happen if one wants to alter
% the layout of a heading that was defined with \cs{@startsection} in the document preamble.
% How this can be done is demonstrated here with the \cs{section}
% command of the \pkg{ltugboat} class.
%
% \subsubsection{Step 1: Getting the template name and the instance values}
%
% The sectioning commands use two template \emph{types}, \texttt{heading} and \texttt{headformat}.
% Compile the following document
%
% \begin{verbatim}
% \DocumentMetadata{}
% \documentclass{ltugboat}
%
% \begin{document}
%
% \section{test} % <--- needed so that the instances get defined
% \ShowInstanceValues{heading}{section-@startsection}
% \ShowInstanceValues{headformat}{section-@startsection}
%
% \end{document}
% \end{verbatim}
%
% This will show the instance values in the log-file:
% \begin{verbatim}
% The instance 'section-@startsection' of type 'heading' has values:
% >  level  =>  1
% >  placement  =>  normal
% >  mark-cmd  =>  \sectionmark {##1}
% >  para-indent  =>  false
% >  before-vspace  =>  8.0pt plus 2.0pt minus 2.0pt
% >  penalty  =>  \c_max_int
% >  after-penalty-vspace  =>  0pt
% >  after-vspace  =>  4.0pt
% >  start-code  =>
% >  final-code  =>
% >  heading-decls  =>  \tubsecfmt
% >  prefix-decls  =>
% >  number-decls  =>
% >  title-decls  =>
% >  subtitle-decls  =>
% >  quote-decls  =>
% >  headformat-instance  =>  section-@startsection
% >  number-format  =>  \theheading
% >  contents-extra  =>
% >  name  =>  section
% >  from template  =>  display.
%
%
% The instance 'section-@startsection' of type 'headformat' has values:
% >  heading-indent  =>  0pt
% >  title-format  =>  \tubsecfmt {##1}
% >  prefix-number-sep  =>  0pt
% >  number-title-sep  =>  1em
% >  from template  =>  hang.
% \end{verbatim}
%
% \subsubsection{Step 2: Get the default template values}
%
% The last line in both lists show after the \texttt{from template} the names of the
% templates of each type. That can be used to get the default values of these templates.
% Compile the following document:%
% \begin{verbatim}
% \DocumentMetadata{}
% \documentclass{ltugboat}
%
% \begin{document}
% \ShowTemplateDefaults{heading}{display}
% \ShowTemplateDefaults{headformat}{hang}
% \end{document}
% \end{verbatim}
%
% This gives in the log and terminal:
% \begin{verbatim}
% The template 'display' of type 'heading' has default values:
% >  level  =>  0
% >  placement  =>  normal
% >  mark-cmd  =>
% >  para-indent  =>  false
% >  before-vspace  =>  0pt
% >  penalty  =>  \c_max_int
% >  after-penalty-vspace  =>  0pt
% >  after-vspace  =>  0pt
% >  start-code  =>
% >  final-code  =>
% >  heading-decls  =>  \normalfont
% >  prefix-decls  =>
% >  number-decls  =>
% >  title-decls  =>
% >  subtitle-decls  =>
% >  quote-decls  =>
% >  headformat-instance  =>  std
% >  number-format  =>  \theheading
% >  contents-extra  =>  .
%
% The template 'hang' of type 'headformat' has default values:
% >  heading-indent  =>  0pt
% >  title-format  =>  ##1
% >  prefix-number-sep  =>  0pt
% >  number-title-sep  =>  1em.
% \end{verbatim}
%
% \subsection{Step 3: Declare the instances}
%
% By comparing the instance values with the default values one can see which values
% should be changed in the instance. The names of the new instances can be
% freely chosen best practice is to use the name
% of the heading command (without a backslash).
%
% This leads then to these declarations (note that in the \texttt{title-format} \verb+##1+ should
% be changed into \verb+#1+):
% \begin{verbatim}
% \DeclareInstance{heading}{section}{display} %#1=heading, #2=name, #3=template name
%  {
%    level          =  1,
%    mark-cmd       =  \sectionmark{#1}, % remove second hash
%    before-vspace  =  8.0pt plus 2.0pt minus 2.0pt,
%    after-vspace   =  4.0pt,
%    heading-decls          =  \tubsecfmt,
%    headformat-instance = section,      % new name
%  }
% \DeclareInstance{headformat}{section}{hang} %#1=heading, #2=name, #3=template name
%  {
%    title-format  =  \tubsecfmt {#1}
%  }
% \end{verbatim}
%
%
%
%
% \subsubsection{Step 4 Redefine the \cs{section} command}
%
% Finally, the heading should be defined to use the new interface.
% \begin{verbatim}
% \DeclareDocumentCommand \section {s ={shorttitle}o m}
%      { \ParseLaTeXeHeading {section} {#1} {#2} {#3} }
% \end{verbatim}
%
%
%
% \section{Setting up \LaTeXe{} heading commands in classes}
%
%  Heading commands are managed by defining an instance of the
%  \texttt{heading} template and then using through \cs{ParseLaTeXeHeading}, e.g.,
% \begin{verbatim}
%   \DeclareDocumentCommand \part {s ={shorttitle}o m}
%       { \ParseLaTeXeHeading {part} {#1} {#2} {#3} }
% \end{verbatim}
%  The name of the \texttt{heading} instance is given in the first argument
%  of \cs{ParseLaTeXeHeading} and it is recommended that classes use the
%  same name as the heading command, to make it easier for users to identify the
%  instance to edit if they want to adapt the command. Examples of instances
%  that mimic the behavior of the heading commands in the standard classes can be found
%  below. Section~\ref{sec:convert} shows how to get instances from commands
%  previously defined with \cs{@startsection}.
%
%  Legacy setup using \cs{@startsection} remains supported albeit
%  not that performant and with some restrictions for the users,
%  see section \ref{sec:startsection} above and in the documentation below.
%
%  In contrast, \cs{secdef} is only rudimentarly supported. It delegates the
%  layout to two commands which can contain arbitrary code (usually
%  hardwired) so that there is no realistic chance to automatically take this
%  apart and figure out what values should be used for what template
%  parameters. We therefore redefine \cs{secdef} and
%  map the standard commands \cs{part}
%  and \cs{chapter} to the standard instance and error if other uses are detected.
%  Classes using \cs{secdef} should setup suitable instances that
%  mimic their current layout, an example can be found for the
%  ams-classes in \texttt{latex-lab-firstaid.dtx}.
%
%
% \section{Open points}
%
% \begin{itemize}
% \item There is no good interface yet to change e.g. the font family of all heading
% commands in one go.
% \item Support for \texttt{titlesec}, see section \ref{sec:titlesec}.
% \end{itemize}
%
% \section{Template types and templates for headings}
%
%    The template(s) for headings expect(s) a large number of
%    positional arguments containing document user data. The
%    document-level command, e.g., \cs{section} may not offer all of
%    them directly, but may do so via a key value interface or not at
%    all. If no interface is provided then the template is passed
%    \cs{NoNalue} . If it is offered via a key value interface,
%    the template receives whatever is set by the user (and
%    \cs{NoNalue} otherwise).
%
%    In my initial implementation I had only the main data as
%    positional arguments, but I came to the conclusion that this
%    scheme here is better going forward.
%
% \subsection{Template types}
%
%    The template type \texttt{heading} has 10 data arguments, which is
%    more than can be specified as positional arguments. For that
%    reason argument \#9 holds 2 brace groups. The alternative would
%    be to specify such arguments as keys, but for a number of reasons
%    I think the approach to put seldom necessary data arguments all
%    in the last positional argument is actually better (besides being faster).
%
% \begin{TemplateInterfaceDescription}{heading}
%    \TemplateArgument{1}{key/value list to alter the default heading parameters}
%    \TemplateArgument{2}{unnumbered heading?}
%    \TemplateArgument{3}{main title of the heading}
%    \TemplateArgument{4}{toc title}
%    \TemplateArgument{5}{running title}
%    \TemplateArgument{6}{bookmark title}
%    \TemplateArgument{7}{nameref text}
%    \TemplateArgument{8}{label for the heading in the form \cs{label}\{\meta{string}\}}
%    \TemplateArgument{9}{\{ sub title \} \{ quotation \}}
%    \TemplateSemantics
%    Handles the layout and processing aspects of a heading.
%
%    Whether or not the heading is numbered is governed through a
%    boolean, expecting the result of an \texttt{s} specification of
%    \cs{NewDocumentCommand} or equivalent, i.e., expects
%    \cs{BooleanTrue} or \cs{BooleanFalse}.
%
%    If the title data is also used for bookmarks, toc, running
%    header, and cross references then it has to be given several times which
%    can be arranged for by the parsing interface command that calls
%    the template instance.
%
%    If the bookmark, toc, or running argument is set to
%    \enquote{empty} then the bookmark, toc or running header should
%    be suppressed by the template. This enables the user on document
%    level to explicitly specify, for example, \texttt{[bookmark=]} to
%    suppress the bookmark.
%
%    The \texttt{nameref} argument is not expected to be empty. Its value
%    should always be used as given if named references are to be
%    generated.
%
%    The label argument either holds a \cs{label} command as provided
%    by the user (or several, see implementation of
%    \cs{ParseLaTeXeHeading}) or it is empty. I.e., it can be directly
%    executed by a template at the right point where the reference
%    counter (if any) has been set up without the need to check its
%    content.
%
%    Argument \#9 holds further user data (in brace groups) which are
%    seldom implemented, but if they are the data is available in a
%    positional argument, which then needs to be taken apart using
%    \cs{@firstoftwo} (for subtitle) or \cs{@secondoftwo} (for a
%    quotation). If no data is provided \cs{NoValue} is used to
%    indicate that.
%
% \end{TemplateInterfaceDescription}
%
%
% \changes{0.9g}{2026-05-24}{Add 'fixed prefix text' as a further
%    argument to the headformat template type}
%
% \begin{TemplateInterfaceDescription}{headformat}
%    \TemplateArgument{1}{key/value list to alter the default headformat parameters}
%    \TemplateArgument{2}{fixed prefix text}
%    \TemplateArgument{3}{formatted heading number}
%    \TemplateArgument{4}{main title of the heading}
%    \TemplateArgument{5}{subtitle}
%    \TemplateArgument{6}{quotation}
%    \TemplateSemantics
%
%    Handles the layout of just the heading label (prefix and number),
%    main title, subtitle, and quotation but not the spatial relation
%    to previous and following text.
%
%    Whether or not the heading is numbered is governed through a
%    boolean, e.g., result of an \texttt{s} specification in
%    \cs{NewDocumentCommand} or equivalent.
%
%    If there is no prefix, subtitle or quotation then this is indicated
%    with \cs{NoValue}.
%
%    The template can ignore the \meta{fixed prefix text} in certain
%    circumstance (or even always). The templates currently
%    implemented to mimic \LaTeXe{} behavior do so in case of
%    unnumbered headings.
%    Same for \meta{subtitle} and \meta{quotation}: both are always
%    ignored by the currently defined templates.
%
%    Note: instead of unnumbered + counter we could just have a single
%    argument containing the number representation (or \cs{NoValue} if
%    not used). The reason that there are two is that this allows us to
%    continue to support \cs{@seccntformat}, but I'm not sure this is a
%    good enough reason, so perhaps this is going to change eventually.
%
% \end{TemplateInterfaceDescription}
%
%
%
% \subsection{Templates}
%
%
% \subsubsection{Templates of type \texttt{heading}}
%
%
%    There are a number of keys that are expected to be recognized by
%    all heading templates (though they may choose not to make use of
%    them). These are listed below instead of being repeated on the
%    actual templates.
%
%    All other keys are either attached to the \texttt{heading} or to
%    the \texttt{headformat} templates. Those that typically vary
%    from heading instance to the next (e.g., \key{heading-decls}) are
%    all declared in the
%    \texttt{heading} templates even if they are actually only used
%    within \texttt{headformat} templates. In other words,
%    \texttt{headformat} templates have a number of implicit
%    variables that they expect to be set.\footnote{Maybe questionable}
%
% \changes{0.9h}{2026-07-04}{Support a \texttt{force-unnumbered} key
%    (tagging/1473)}
%
% \begin{TemplateDescription}{heading}{\meta{all}}
%
% \changes{0.9h}{2026-06-21}{Support \texttt{column-spanning} key (tagging/1436)}
%
%  \TemplateKey{name}{tokenlist}
%              {Referenceable name of the heading instance. String that
%               is acceptable in csnames for use in building counter
%               names, etc.}{}
%  \TemplateKey{parent-name}{tokenlist}
%              {Name of the next higher heading instance. If not
%               given, then the internal heading level of the heading
%               instance is set to \texttt{0} --- not yet
%               implemented/may vanish}{}
%  \TemplateKey{reset-counter}{tokenlist}
%              {Name of the heading instance that should reset the
%               numbering of this heading level (if any) --- not yet
%               implemented/may vanish}{}
%  \TemplateKey{level}{integer}
%              {Sets the internal heading-level rather than deducing
%               it from \key{parent-name}. Can be used to specify the
%               top-level heading if not \texttt{0}, or all headings
%               in legacy implementations, e.g., through \cs{@startsection}}{}
%
%  \TemplateKey{force-unnumbered}{boolean}
%              {This heading is never numbered, even if explicitly requested
%               in the optional argument to the heading. If
%               \texttt{false} then numbering is determined in the normal
%               way (through \texttt{secnumdepth}, \texttt{*}, or a
%               setting in the optional argument to the heading).}{false}
%
%  \TemplateKey{placement}{choice}
%              {Set the heading placement, i.e., the behavior of the
%               heading with respect to page breaks. Allowed values
%               are
%               \texttt{page} (heading forms a page if its own),
%               \texttt{top} (heading starts a new page),
%               \texttt{normal} (heading can appear anywhere on the
%               page),
%               \texttt{ragged} (like \texttt{normal} but if a
%               pagebreak is taken before the heading then the
%               previous page is set ragged and not stretched).
%               Further possibilities might be
%               \texttt{rectopage} and \texttt{rectotop} if we
%               implement that.}{\texttt{normal}}
%
%  \TemplateKey{start-code}{tokenlist}
%              {Default value is set by the \key{placement}
%    key. Executed before the heading starts, so can issue, for
%    example, a \cs{clearpage}}
%              {}
%
%  \TemplateKey{final-code}{tokenlist}
%              {Default value is set by the \key{placement}
%    key. Executed after the heading is typeset. Can set up code for
%    putting the heading on a page by its own, or arrange for
%    paragraph handling of a following paragraph, etc.}
%              {}
%
%
%  \TemplateKey{column-spanning}{boolean}
%              {If true produces a heading that spans columns in
%               \texttt{twocolumn} typesetting.  Requires
%               \key{placement} \texttt{=} \keyvalue{top} (and adjusts
%               if necessary) and only has an effect
%               if the columns are produced via the \texttt{twocolumn}
%               class option and not when using \env{multicol}. This
%               might get extended when we refactor the OR handling.}{false}
%
%  \TemplateKey{prefix}{tokenlist}
%              {A fixed string, such as \enquote{Chapter}, that can be
%               used together with the number (if any) to form a
%               \enquote{heading label}. Usage and placement is up to
%               the template, so it could be placed after the number
%               by the template (in which case it isn't really a
%               prefix).} {\cs{NoValue}}
%
%  \TemplateKey{mark-cmd}{function(1)}
%              {Function that receives the \meta{running} argument and
%               creates a suitable mark insertion}
%              {\texttt\textbackslash\meta{name}\texttt{mark}}
%
%    \TemplateSemantics
%
%    The above keys should be implemented by all heading templates.
%
%    At the moment I have retained the \LaTeXe{} interfaces for marks,
%    e.g., one has to set up \cs{chaptermark}, \cs{sectionmark},
%    etc.\ but I'm not sure this should stay (even though it is
%    certainly simpler from a compatibility perspective).
%
%    All templates should set up \cs{theheading} to correspond to
%    \cs{the\meta{name}}.
% \end{TemplateDescription}
%
%
% \begin{TemplateDescription}{heading}{display}
%
%  \TemplateKey{para-indent}{boolean}
%              {Should the paragraph after the heading be indented?}
%              {false}
%
%  \TemplateKey{before-vspace}{skip}
%              {Vertical space before the heading if there is no page
%               or column break. If there is one it vanishes.
%               In particular this means it will not be used in the
%              heading \texttt{placement}s \texttt{page} or \texttt{top}}
%              {0pt}
%
%  \TemplateKey{penalty}{integer}
%              {Penalty to break before the heading. The default
%    (\TeX's largest integer) indicates that no penalty was set in
%    which case \cs{@secpenalty} is used (to support the \LaTeXe{} interface).}
%              {\number\maxdimen}
%
%  \TemplateKey{after-penalty-vspace}{skip}
%              {Vertical space before the heading but after the
%    penalty for the heading. If the penalty results in a page or
%    column break, this space remains at the top of the page}
%              {0pt}
%
%  \TemplateKey{after-vspace}{skip}
%              {Vertical space after the heading}
%              {0pt}
%
%  \TemplateKey{heading-decls}{tokenlist}
%              {Declarations (such as font or color settings) applied
%               to all heading elements, i.e., number, title,
%               subtitle, and quotation, if present.
%               Note that color commands (unless \pkg{luacolor} is used)
%               introduce a break point before the heading and therefore one should either
%               surround color commands with \cs{SaveLastSkip} and \cs{RestoreLastSkip} or
%               to use the keys \texttt{prefix-decls}, \texttt{number-decls},
%               \texttt{title-decls}, etc.\ instead.}
%              {\cs{normalfont}}
%
%  \TemplateKey{prefix-decls}{tokenlist}
%              {Declarations (such as font or color settings) applied
%               to the heading prefix, overwriting the setting
%               of \key{heading-decls}.}
%              {\meta{empty}}
%
%  \TemplateKey{number-decls}{tokenlist}
%              {Declarations (such as font or color settings) applied
%               to the heading  number, overwriting the setting
%               of \key{heading-decls}.}
%              {\meta{empty}}
%
%  \TemplateKey{title-decls}{tokenlist}
%              {Declarations (such as font or color settings) applied
%               to the heading  title, overwriting the setting
%               of \key{heading-decls}.}
%              {\meta{empty}}
%
%  \TemplateKey{subtitle-decls}{tokenlist}
%              {Declarations (such as font or color settings) applied
%               to the heading  subtitle, overwriting the setting
%               of \key{heading-decls}.}
%              {\meta{empty}}
%
%  \TemplateKey{quote-decls}{tokenlist}
%              {Declarations (such as font or color settings) applied
%               to the heading  quote, overwriting the setting
%               of \key{heading-decls}.}
%              {\meta{empty}}
%
%  \TemplateKey{number-format}{function(1)}
%              {Code that produces a formatted version of the
%               heading number
%               including any ornamentations. Its argument is the
%               counter name for the head. However, instead of using
%               a specific counter representations, e.g.,
%               \cs{thesection}, it
%               can refer to the counter representation for the
%               current heading counter via \cs{theheading} and ignore
%               the argument.}
%              {\cs{theheading}}
%
%  \TemplateKey{contents-extra}{tokenlist}
%              {Code containing \cs{addcontents} calls to write to
%               files like \texttt{.lot} or \texttt{.lot}}
%              {\meta{empty}}
%
%
%  \TemplateKey{headformat-instance}{instance}
%              {Template instances of type \texttt{headformat}}
%              {std}
%
%    \TemplateSemantics
%
%    Several of the key names are simply bad and need revision!
% \end{TemplateDescription}
%
%
%
%
% \begin{TemplateDescription}{heading}{runin}
%
%  \TemplateKey{before-vspace}{skip}
%              {Vertical space before the heading if there is no page
%               or column break. If there is one it vanishes.}
%              {0pt}
%
%  \TemplateKey{penalty}{integer}
%              {Penalty to break before the heading. The default
%    (\TeX's largest integer) indicates that no penalty was set in
%    which case \cs{@secpenalty} is used.}
%              {\number\maxdimen}
%
%  \TemplateKey{after-penalty-vspace}{skip}
%              {Vertical space before the heading but after the
%    penalty for the heading. If the penalty results in a page or
%    column break, this space remains at the top of the page. It is
%    also applied if the heading is a \texttt{page} or \texttt{top} heading.}
%              {0pt}
%
%  \TemplateKey{after-vspace}{skip}
%              {Vertical space after the heading -- ignored in runin
%               headings so should be dropped!}
%              {0pt}
%
%  \TemplateKey{heading-decls}{tokenlist}
%              {Declarations (such as font or color settings) applied
%               to all heading elements, i.e., number, title,
%               subtitle, and quotation, if present.}
%              {\cs{normalfont}}
%
%  \TemplateKey{prefix-decls}{tokenlist}
%              {Declarations (such as font or color settings) applied
%               to the heading prefix, overwriting the setting
%               of \key{heading-decls}.}
%              {\meta{empty}}
%
%  \TemplateKey{number-decls}{tokenlist}
%              {Declarations (such as font or color settings) applied
%               to the heading  number, overwriting the setting
%               of \key{heading-decls}.}
%              {\meta{empty}}
%
%  \TemplateKey{title-decls}{tokenlist}
%              {Declarations (such as font or color settings) applied
%               to the heading  title, overwriting the setting
%               of \key{heading-decls}.}
%              {\meta{empty}}
%
%  \TemplateKey{subtitle-decls}{tokenlist}
%              {Declarations (such as font or color settings) applied
%               to the heading  subtitle, overwriting the setting
%               of \key{heading-decls}.}
%              {\meta{empty}}
%
%  \TemplateKey{quote-decls}{tokenlist}
%              {Declarations (such as font or color settings) applied
%               to the heading  quote, overwriting the setting
%               of \key{heading-decls}.}
%              {\meta{empty}}
%
%  \TemplateKey{number-format}{function(1)}
%              {Code that produces a formatted version of the
%               heading number
%               including any ornamentations. Its argument is the
%               counter name for the head. However, instead of using
%               a specific counter representations, e.g.,
%               \cs{thesection}, it
%               can refer to the counter representation for the
%               current heading counter via \cs{theheading} and ignore
%               the argument.}
%              {\cs{theheading}}
%
%  \TemplateKey{headformat-instance}{instance}
%              {Template instances of type \texttt{headformat}}
%              {std}
%
%    \TemplateSemantics
%
%    Several of the key names are simply bad and need revision!
% \end{TemplateDescription}
%
%
%
%
% \subsubsection{Templates of type \texttt{headformat}}
%
%    At the moment all templates of this type assume that placement of
%    prefix, number, title is done in exactly this order. Anything
%    else would require defining further templates.
%
%    TODO: consider a more versatile mechanism (like in theorem-like
%    templates) to allow for more flexible placements without the need
%    to define additional templates. There is now the new order key
%    mechanism to make this happen so the templates are going to
%    change soon (and will different keys and some additional ones)!
%
% \begin{TemplateDescription}{headformat}{hang}
%
%  \TemplateKey{heading-indent}{dimen}
%              {Horizontal space before the heading (shifting it to
%               the right in a LR typesetting context)}
%              {0pt}
%
%  \TemplateKey{title-format}{tokenlist}
%              {Code executed directly before the heading is typeset
%               and after the vertical spacing is done. The code takes an argument,
%               e.g., \cs{MakeUppercase}}
%              {\meta{\#1}}
%
%  \TemplateKey{prefix-number-sep}{tokenlist}
%              {Token list that can be used in the assignment to a
%               \TeX{} dimension (can contain \texttt{em} or
%               \texttt{ex} values) specifying the separation between
%               title prefix (if used) and title number. Evaluated after fonts for
%               title text have been set up, i.e., the \texttt{em} will be based
%               on the then current font.}
%              {.5em}
%
%  \TemplateKey{number-title-sep}{tokenlist}
%              {Token list that can be used in the assignment to a
%               \TeX{} dimension (can contain \texttt{em} or
%               \texttt{ex} values) specifying the separation between
%               title number and title text. Evaluated after fonts for
%               title text have been set up, i.e., the \texttt{em} will be based
%               on the then current font.}
%              {1em}
%
%    \TemplateSemantics
%
%    Implements a heading layout where number and title start on the
%    same line and the title is hanging off from  that if the title
%    has more than one line. It is what \LaTeX{} always used by
%    default for \cs{section}, \cs{subsection}, and
%    \cs{subsubsection}.
%
%    Several of the key names are simply bad and need a revision!
% \end{TemplateDescription}
%
%
% \begin{TemplateDescription}{headformat}{runin}
%
%  \TemplateKey{heading-indent}{dimen}
%              {Horizontal space before the heading (shifting it to
%               the right in a LR typesetting context)}
%              {0pt}
%
%  \TemplateKey{title-format}{tokenlist}
%              {Code executed directly before the heading is typeset
%               and after the vertical spacing is done. The code can take an argument,
%               e.g., \cs{MakeUppercase}}
%              {\meta{empty}}
%
%  \TemplateKey{prefix-number-sep}{tokenlist}
%              {Token list that can be used in the assignment to a
%               \TeX{} dimension (can contain \texttt{em} or
%               \texttt{ex} values) specifying the separation between
%               title prefix (if used) and title number. Evaluated after fonts for
%               title text have been set up, i.e., the \texttt{em} will be based
%               on the then current font.}
%              {.5em}
%
%  \TemplateKey{number-title-sep}{tokenlist}
%              {Token list that can be used in the assignment to a
%               \TeX{} dimension (can contain \texttt{em} or
%               \texttt{ex} values) specifying the separation between
%               title number and title text. Evaluated after fonts for
%               title text have been set up, i.e., the \texttt{em} will be based
%               on the then current font.
%
%               In the hang template it is a horizontal dimension!}
%              {1em}
%
%    \TemplateSemantics
%
%    Implements a heading layout where number and title start on the
%    same line but then continue with the following paragraph on the
%    same line (or the next if the title overflows, i.e., the title is
%    run-in. It is what \LaTeX{} always used by default for
%    \cs{paragraph} and \cs{subparagraph}.
%
%    Several of the key names are simply bad and need a revision!
% \end{TemplateDescription}
%
%
% \begin{TemplateDescription}{headformat}{display}
%
%  \TemplateKey{heading-indent}{dimen}
%              {Horizontal space before the heading (shifting it to
%               the right in a LR typesetting context)}
%              {0pt}
%  \TemplateKey{title-format}{tokenlist}
%              {Code executed directly before the heading is typeset
%               and after the vertical spacing is done. The code can take an argument,
%               e.g., \cs{MakeUppercase}}
%              {\meta{\#1}}
%
%  \TemplateKey{prefix-number-sep}{tokenlist}
%              {Token list that can be used in the assignment to a
%               \TeX{} dimension (can contain \texttt{em} or
%               \texttt{ex} values) specifying the separation between
%               title prefix (if used) and title number. Evaluated after fonts for
%               title text have been set up, i.e., the \texttt{em} will be based
%               on the then current font.}
%              {.5em}
%
%  \TemplateKey{number-title-sep}{tokenlist}
%              {Token list that can be used in the assignment to a
%               \TeX{} dimension (can contain \texttt{em} or
%               \texttt{ex} values) specifying the separation between
%               title number and title text. Evaluated after fonts for
%               title text have been set up, i.e., the \texttt{em} will be based
%               on the then current font.
%         \endgraf
%               In the display template it is a vertical dimension!}
%              {20 pt}
%
%    \TemplateSemantics
%
%    Implements a heading layout where number and title are vertically
%    separated. It is what \LaTeX{} always used by default for
%    \cs{chapter} and \cs{part}.
%
%    Several of the key names are simply bad and need a revision!
% \end{TemplateDescription}
%
%
%
%
% \subsection{Default instances}
%
%    These instances are set up to mimic the design of the standard
%    \LaTeX{} classes. For other classes they could be adjusted by
%    changing the instance values and/or by basing them on a different
%    template.
%
% \subsubsection{Instances of \texttt{heading} templates}
%
% \begin{description}
%
% \item[\texttt{part} (instance of \texttt{display} template)] Used for the
%    \cs{part} command.
%
% \item[\texttt{chapter} (instance of \texttt{display} template)] Used for the
%    \cs{chapter} command.
%
% \item[\texttt{section} (instance of \texttt{display} template)] Used for the
%    \cs{section} command.
%
% \item[\texttt{subsection} (instance of \texttt{display} template)] Used for
%    the \cs{subsection} command.
%
% \item[\texttt{subsubsection} (instance of \texttt{display} template)] Used for
%    the \cs{subsubsection} command.
%
% \item[\texttt{paragraph} (instance of \texttt{runin} template)] Used for the
%    \cs{paragraph} command.
%
% \item[\texttt{subparagraph} (instance of \texttt{runin} template)] Used for
%    the \cs{subparagraph} command.
%
% \end{description}
%
%
% \subsubsection{Instances of \texttt{headformat} templates}
%
% \begin{description}
%
% \item[\texttt{part} (instance of \texttt{display} template)] Used in
%    \texttt{heading} instance for \cs{part}.
%
% \item[\texttt{chapter} (instance of \texttt{display} template)] Used in
%    \texttt{heading} instance for \cs{chapter}. By default identical
%    to the one used for \cs{part}.
%
% \item[\texttt{std} (instance of \texttt{hang} template)] Used as
%    default in the heading template if nothing else is specified.
%
% \item[\texttt{section} (instance of \texttt{hang} template)] Used in
%    \texttt{heading} instance for \cs{section}. By default identical
%    to the \texttt{std} instance.
%
% \item[\texttt{subsection} (instance of \texttt{hang} template)] Used in
%    \texttt{heading} instance for \cs{subsection}. By default identical
%    to the \texttt{std} instance.
%
% \item[\texttt{subsubsection} (instance of \texttt{hang} template)] Used in
%    \texttt{heading} instance for \cs{subsubsection}. By default identical
%    to the \texttt{std} instance.
%
% \item[\texttt{paragraph} (instance of \texttt{runin} template)] Used in
%    \texttt{heading} instance for \cs{paragraph}.
%
% \item[\texttt{subparagraph} (instance of \texttt{runin} template)] Used in
%    \texttt{heading} instance for \cs{subparagraph}.
%
% \end{description}
%
%
%
%
% \section{Support for legacy classes and packages}
%
% \subsection{Support classes based on legacy \LaTeXe{} interfaces}
%
% \DescribeMacro\@startsection
%    The \cs{@startsection} command has the following syntax:
% \begin{verbatim}
%  \@startsection{name}{level}{indent}{beforeskip}{afterskip}{style}
% \end{verbatim}
%    with a special logic that the sign of \meta{beforeskip} determines
%    display or runin heading and that of \meta{afterskip} whether or
%    not the next paragraph is indented.
%
%    All arguments can be cleanly mapped to \texttt{heading} and
%    \texttt{headformat} templates. Thus, if encountered suitable
%    instances are automatically declared unless they already exist.
%
%
%
% \DescribeMacro\secdef
%    In contrast, \cs{secdef} only does the parsing and delegates the
%    layout to two commands which can contain arbitrary code (usually
%    hardwired) so that there is no realistic chance to take this
%    apart and figure out what values should be used for what template
%    parameters.
%
%    We therefore do not attempt to model this, but instead just use
%    the standard layout from \LaTeX's standard classes for
%    \cs{chapter} and \cs{part} if we can identify that the \cs{secdef}
%    is used to define one of these.
%
%    Maybe we can try at some stage to get some static analysis tool
%    going.
%
%
% \subsection[label=sec:titlesec]{Support for the \pkg{titlesec} package interfaces}
%  TODO
%
% \noindent
% \DescribeMacro\titleformat
% The \cs{titleformat} declaration has the following syntax:
% \begin{verbatim}
%  \titleformat{cmd}[shape]{format}{label}{sep}{before-code}[after-code]
% \end{verbatim}
%
% \noindent
% \DescribeMacro\titlespacing
% The \cs{titlespacing} declaration has the following syntax:
% \begin{verbatim}
%  \titlespacing*{cmd}{left-sep}{before-vspace}{after-vspace}[right-sep]
% \end{verbatim}
%
% \section{Support for links}
%
% All heading commands (numbered and unnumbered) should contain support for
% active links directly. hyperref does not patch the new heading commands!
% As \cs{refstepcounter} is not used there is no automatic target.
%
% This means that all definitions should contain at an appropriate place
% a \cs{MakeLinkTarget} command. Typically numbered heading commands will use
% \verb+\MakeLinkTarget{+\meta{counter}\verb+}+ while unnumbered heading commands
% use \verb+\MakeLinkTarget[+\meta{counter}\verb+]{}+.
%
% The definition must take care that the target is not separated from the heading
% by a page break. It also should not affect spacing.
% The target should be placed so that a jump to the target gives
% a satisfying user experience, in most cases the best places is at the left margin
% a bit above the heading.
%
% The targets create also structure destinations that
% are used by the tagging code. It is therefore important that the targets
% are in the right place in relation to the tagging commands.
%
% \section{Bookmarks}
%
% Bookmarks are created by the \cs{addcontentsline} command, more precisely in the
% new latex-lab toc code a hook with arguments is inserted at the begin of the command
% which contains the command that creates the bookmark. The arguments of \cs{addcontentsline}
% and so also of the hook are the type of the toc,
% the level name and the (short-)title of the heading. To pass a differing
% bookmark text the code uses \cs{texorpdfstring} in the \cs{addcontentsline}.
% \ufi{check if this is still the implementation ...}
% \section{Tagging support}
%
% Tagging of heading commands has to do two tasks:
%  \begin{itemize}
%  \item surround the whole section (heading and text) with a \texttt{Sect} structure
%  \item tag the heading with an Hn structure.
%  \end{itemize}
% This is done with tagging sockets which are documented in the code and in \texttt{latex-lab-sec}.
%
% \section{Debugging support}
%
% \begin{function}{\DebugHeadingsOn,\DebugHeadingsOff, \head_debug_on:, \head_debug_off:}
%
% These commands enable/disable debugging messages.
%
% \end{function}
%
%
%
% \end{documentation}
%
% \StopEventually{\setlength\IndexMin{200pt}  \PrintIndex  }
%
%
%
% \begin{implementation}
%
% \section{The Implementation}
%
%
%    \begin{macrocode}
%<*package>
%<@@=head>
%    \end{macrocode}
%
%
%    \begin{macrocode}
\ProvidesExplPackage
 {latex-lab-testphase-sec-template}
 {\ltlabsecIIdate}
 {\ltlabsecIIversion}
 {heading implementation}
%    \end{macrocode}
%
% \changes{v0.9c}{2026-03-12}{Switch from \texttt{x}- to \texttt{e}-type
%   expansion in expl3 code}
%
% \bigskip
%
% \subsection{Debugging}
%
%  \begin{variable}{\g_@@_debug_bool}
%
%    \begin{macrocode}
\bool_new:N \g_@@_debug_bool
%    \end{macrocode}
%  \end{variable}
%
%
%  \begin{macro}{\@@_debug:n,\@@_debug_typeout:n}
%
%    \begin{macrocode}
\cs_new_eq:NN \@@_debug:n \use_none:n
\cs_new_eq:NN \@@_debug_typeout:n \use_none:n
%    \end{macrocode}
%  \end{macro}
%
%  \begin{macro}{\head_debug_on:,\head_debug_off:,
%                \@@_debug_gset:}
%    \begin{macrocode}
\cs_new_protected:Npn \head_debug_on:
  {
    \bool_gset_true:N \g_@@_debug_bool
    \@@_debug_gset:
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new_protected:Npn \head_debug_off:
  {
    \bool_gset_false:N \g_@@_debug_bool
    \@@_debug_gset:
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new_protected:Npn \@@_debug_gset:
  {
    \cs_gset_protected:Npe \@@_debug:n ##1
      { \bool_if:NT \g_@@_debug_bool {##1} }
    \cs_gset_protected:Npe \@@_debug_typeout:n ##1
      { \bool_if:NT \g_@@_debug_bool { \typeout{[head]~ ##1} } }
  }
%    \end{macrocode}
%  \end{macro}
%
%
%  \begin{macro}{\DebugHeadingsOn,\DebugHeadingsOff}
%
%    \begin{macrocode}
\cs_new_protected:Npn \DebugHeadingsOn  { \head_debug_on:  }
\cs_new_protected:Npn \DebugHeadingsOff { \head_debug_off: }
%    \end{macrocode}
%
%    \begin{macrocode}
\DebugHeadingsOff
%    \end{macrocode}
%  \end{macro}
%
%  \begin{macro}{\@@_show_arguments:nnnnnn}
%    Some debug data \ldots
%    \begin{macrocode}
\cs_new:Npn \@@_show_arguments:nnnnnn #1#2#3#4#5#6 {
  \@@_debug_typeout:n{---------~ Headformat~ instance~ arguments:}
  \@@_debug_typeout:n{1:~ keys~ =~ \exp_not:n{#1}}
  \@@_debug_typeout:n{2:~ prefix~ =~ \exp_not:n{#2}}
  \@@_debug_typeout:n{3:~ number~ =~ \exp_not:n{#3}}
  \@@_debug_typeout:n{4:~ title~ =~ \exp_not:n{#4}}
  \@@_debug_typeout:n{5:~ subtitle~ =~ \exp_not:n{#5}}
  \@@_debug_typeout:n{6:~ quotation~ =~ \exp_not:n{#6}}
}
%    \end{macrocode}
%  \end{macro}
%  \begin{macro}{\@@_show_arguments:nnnnnnnnn}
%    Some debug data \ldots
%    \begin{macrocode}
\cs_new:Npn \@@_show_arguments:nnnnnnnnn #1#2#3#4#5#6#7#8#9 {
  \@@_debug_typeout:n{---------~ Heading~ instance~ arguments:}
  \@@_debug_typeout:n{1:~ keys~ =~ \exp_not:n{#1}}
  \@@_debug_typeout:n{2:~ unnumbered~ =~ \exp_not:n{#2}}
  \@@_debug_typeout:n{3:~ title~ =~ \exp_not:n{#3}}
  \@@_debug_typeout:n{4:~ toc~ =~ \exp_not:n{#4}}
  \@@_debug_typeout:n{5:~ running~ =~ \exp_not:n{#5}}
  \@@_debug_typeout:n{6:~ bookmark~ =~ \exp_not:n{#6}}
  \@@_debug_typeout:n{7:~ nameref~ =~ \exp_not:n{#7}}
  \@@_debug_typeout:n{8:~ label~ =~ \exp_not:n{#8}}
  \@@_debug_typeout:n{9:~ subtitle | quote ~ =~ \exp_not:n{#9}}
}
%    \end{macrocode}
%  \end{macro}
%
% \subsection{Temp variable(s)}
% \begin{variable}{\l_@@_tmpa_tl}
%    \begin{macrocode}
\tl_new:N\l_@@_tmpa_tl
%    \end{macrocode}
% \end{variable}
%
% \subsection{variable(s)}
%  These token lists are automatically declared by the key machinery.
%    \begin{macrocode}
%\tl_new:N \l_@@_bookmark_tl
%\tl_new:N \l_@@_running_tl
%\tl_new:N \l_@@_toc_tl
%\tl_new:N \l_@@_nameref_tl
%\tl_new:N \l_@@_subtitle_tl
%\tl_new:N \l_@@_quote_tl
%\bool_new:N l_@@_unnumbered_bool
%    \end{macrocode}
%
% \begin{variable}{
%  \l_@@_label_tl,
%  \l_@@_instance_keys_tl,
%  \l_@@_typeset_number_tl,
%  \l_@@_saved_secnumdepth_tl,
%  \l_@@_title_tl,
%  \l_@@_placement_tl}
%
% But this token lists needs a declaration:
%
%    \begin{macrocode}
\tl_new:N\l_@@_label_tl
\tl_new:N\l_@@_instance_keys_tl
\tl_new:N\l_@@_typeset_number_tl
\tl_new:N\l_@@_saved_secnumdepth_tl
\tl_new:N \l_@@_title_tl
\tl_new:N \l_@@_placement_tl
%    \end{macrocode}
% \end{variable}
%
% \subsection{New user commands}
%
% \begin{macro}{\theheading}
% This command expands to \cs{thechapter}, \cs{thesection} etc
% in every heading command.
%    \begin{macrocode}
\tl_new:N\theheading
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\partmark}
% This replaces the fix \verb+\markboth{}{}+ or similar in the standard \cs{part}
% definition. As the command is already defined in some classes (like \pkg{memoir}),
% we provide it through a hook.
%    \begin{macrocode}
\AddToHook{class/after}{\providecommand*\partmark[1]{\markboth{}{}}}
%    \end{macrocode}
% \end{macro}
%
% \subsection{The \LaTeXe{} parsing interface}
%
%    \LaTeXe{} provides heading commands with a starred form
%    (unnumbered) and one optional argument (to specify an alternative
%    toc/running head). We augment this slightly by supporting a key
%    value interface in the optional argument. This is handled by
%    defining the commands through \cs{ParseLaTeXeHeading}. This
%    should happen in the document class.
%
%
%  \begin{macro}{\ParseLaTeXeHeading}
%
%    \cs{ParseLaTeXeHeading} arguments:
%    \begin{itemize}
%    \item[1:] instance name to use (of type \enquote{heading})
%    \item[2:] numbered? boolean
%    \item[3:] shorttitle or key/val for layout adjustments and individual
%              title settings
%    \item[4:] main title
%    \end{itemize}
%
%    This command handles the document input that may be hidden in the
%    optional argument, i.e., special data for toc, running (header),
%    bookmark, label, and for more specialized headings subtitle and
%    quote. It also handles the legacy case that the optional argument is just
%    an alternate title to be used for toc, running, and bookmark
%    (through the key shorttitle to which it gets converted).
%
%    \begin{macrocode}
\cs_new_protected:Npn \ParseLaTeXeHeading #1 #2 #3 #4 {
%    \end{macrocode}
%
%    \begin{macrocode}
  \@@_debug_typeout:n{==================================}
  \@@_debug_typeout:n{#1:~ \IfBooleanT{#2}{*}
                \IfValueT{#3}{[\exp_not:n{#3}]}
                {\exp_not:n{#4}}}
%    \end{macrocode}
%    We first check if the title argument contains a \cs{label}
%    command. If yes, we remove it and add it to \cs{l_@@_label_tl}
%    (and if more than one all of them) and save the rest of the main title in
%    \cs{l_@@_title_tl} for later use. If there was no \cs{label}
%    command then \cs{l_@@_title_tl} is set to \texttt{\#4}.
%    \begin{macrocode}
  \@@_find_label:w #4 \label\q_no_value \@@_find_label:w
%    \end{macrocode}
%    By default toc, running, and bookmark use the data provided by
%    the main title. However, if the second argument is true (i.e., a
%    star was given) they are all suppressed (because this is the \LaTeXe{} logic).
%    \begin{macrocode}
  \IfBooleanTF{#2}
    {
      \tl_clear:N \l_@@_toc_tl
      \tl_clear:N \l_@@_running_tl
      \tl_clear:N \l_@@_bookmark_tl
      \bool_set_true:N \l_@@_unnumbered_bool
    }
    {
      \tl_set_eq:NN \l_@@_toc_tl      \l_@@_title_tl
      \tl_set_eq:NN \l_@@_running_tl  \l_@@_title_tl
      \tl_set_eq:NN \l_@@_bookmark_tl \l_@@_title_tl
      \bool_set_false:N \l_@@_unnumbered_bool
    }
%    \end{macrocode}
%    The nameref always starts out matching the main title.
%    \begin{macrocode}
  \tl_set_eq:NN \l_@@_nameref_tl \l_@@_title_tl
%    \end{macrocode}
%    Normally we don't have a subtitle or quote unless they are
%    explicitly given through keys, so we start with \cs{c_novalue_tl}
%    \begin{macrocode}
  \tl_set_eq:NN \l_@@_subtitle_tl \c_novalue_tl
  \tl_set_eq:NN \l_@@_quote_tl    \c_novalue_tl
%    \end{macrocode}
%    If the optional argument is empty we set the
%    \cs{l_@@_instance_keys_tl} to empty, otherwise process the
%    key/val list setting the keys defined in the module \enquote{head}. This
%    overwrites the defaults specified above if keys like \enquote{toc} are in
%    the list. All the key/vals unknown by that module are put into
%    \cs{l_@@_instance_keys_tl} which may or may not make this token
%    list non-empty.
%
%    If the user has a \key{label} key and also a \cs{label} in the
%    main title argument then the latter is ignored (no error checking
%    for that). We could alternatively set all labels we find,
%    perhaps that is the better approach?
%    \begin{macrocode}
  \IfNoValueTF { #3 }
    { \tl_clear:N \l_@@_instance_keys_tl }
    { \keys_set_known:nnN {heading} { #3 } \l_@@_instance_keys_tl }
%    \end{macrocode}
%
%    Finally we call the heading instance using the collected
%    mandatory arguments. To simplify downstream processing we pass
%    the values not the container tokenlists resulting from the above
%    processing.\footnote {I think this is a common requirement and
%    perhaps \cs{UseInstance} should really o-expand all arguments it
%    receives.}
%    \begin{macrocode}
  \@@_debug_typeout:n{use~ 'heading'~ instance:~ #1 }
  \use:e {
    \exp_not:N \UseInstance{heading}{#1}
              { \exp_not:o \l_@@_instance_keys_tl }
              { \bool_if:NTF \l_@@_unnumbered_bool \BooleanTrue \BooleanFalse }
              { \exp_not:o \l_@@_title_tl}
              { \exp_not:o \l_@@_toc_tl }
              { \exp_not:o \l_@@_running_tl }
              { \exp_not:o \l_@@_bookmark_tl }
              { \exp_not:o \l_@@_nameref_tl }
              { \exp_not:o \l_@@_label_tl }
              { { \exp_not:o \l_@@_subtitle_tl }
                { \exp_not:o \l_@@_quote_tl    } }
  }
}
%    \end{macrocode}
%
%    Syntax keys that can appear in the optional argument of headings
%    parsed by \cs{ParseLaTeXeHeading}. All other keys used there are
%    passed to the heading instance to overwrite instance setting.
%
%    \begin{macrocode}
\keys_define:nn {heading} {
  , shorttitle .meta:n    =
      {toc = {#1} , running = {#1} , bookmark = {#1} , nameref= {#1} }
  , bookmark   .tl_set:N  = \l_@@_bookmark_tl
  , running    .tl_set:N  = \l_@@_running_tl
  , toc        .tl_set:N  = \l_@@_toc_tl
  , nameref    .tl_set:N  = \l_@@_nameref_tl
%
  , numbered   .bool_set_inverse:N = \l_@@_unnumbered_bool
  , numbered   .default:n = true
  , unnumbered .bool_set:N = \l_@@_unnumbered_bool
  , unnumbered .default:n = true
%
  , subtitle   .tl_set:N  = \l_@@_subtitle_tl
  , quote      .tl_set:N  = \l_@@_quote_tl
%    \end{macrocode}
%    We collect labels together with their \cs{label} command in case
%    there is more than one. This way we can later simply execute
%    \cs{l_@@_label_tl} without any status checks.
%    \begin{macrocode}
  , label      .code:n    = \tl_put_right:Nn \l_@@_label_tl { \label{#1} }
}
%    \end{macrocode}
%
%
%  \end{macro}
%
%  \begin{macro}{\@@_find_label:w}
%    A simple-minded check for an existing \cs{label} command in the
%    main title (could be done better I guess). We add
%    \cs{label}\cs{q_no_value} at the end of the argument, so that we
%    can be sure to find something.
%
%    As currently implemented the spaces on both sides of a \cs{label}
%    command survive if it is removed. This may be an issue in which
%    case this may need some adjustments.
%    \begin{macrocode}
\cs_new:Npn \@@_find_label:w #1 \label #2#3 \@@_find_label:w {
%    \end{macrocode}
%    If the token after \cs{label} is \cs{q_no_value} then the title
%    had no label and we set the two variables accordingly.
%    \begin{macrocode}
  \quark_if_no_value:nTF {#2}
     {
       \@@_debug_typeout:n{---~no~label }
       \tl_clear:N \l_@@_label_tl
       \tl_set:Nn\l_@@_title_tl {#1#3}
     }
%    \end{macrocode}
%    Otherwise, there was a real \cs{label} command and \texttt{\#2}
%    holds the label string.
%    \begin{macrocode}
     {
       \@@_debug_typeout:n{---~label~found~#2}
       \tl_set:Nn\l_@@_label_tl { \label{#2} }
%    \end{macrocode}
%    To construct the value for \cs{l_@@_title_tl} we have to get rid
%    of the two tokens we added at its end, this is done with
%    \cs{@@_find_label_aux:w}.
%    \begin{macrocode}
       \tl_set:Nn\l_@@_title_tl {#1}
       \@@_find_label_aux:w #3\@@_find_label_aux:w
     }
     \@@_debug_typeout:n{---~return:~ '\exp_not:o \l_@@_title_tl' }
}
%    \end{macrocode}
%    There is at least one more \cs{label} now and the token after it
%    should be our \cs{q_no_value}. If not then the title argument had
%    at least 2 labels and we collect the newly found one and recurse.
%    \begin{macrocode}
\cs_new:Npn \@@_find_label_aux:w #1 \label #2#3 \@@_find_label_aux:w {
%    \end{macrocode}
%    The \texttt{\#1} may not be everything we have to pick up but we
%    know for sure that it belongs to the title.
%    \begin{macrocode}
  \tl_put_right:Nn \l_@@_title_tl { #1 }
%    \end{macrocode}
%    Now let's see if we are at the end of the argument. If not pick
%    up the newly found \cs{label} and recurse on the remaining material.
%    \begin{macrocode}
  \quark_if_no_value:nF {#2}
    {
      \@@_debug_typeout:n{---~ extra~ label~ '#2'~ found }
      \tl_put_right:Nn \l_@@_label_tl { \label{#2} }
      \@@_find_label_aux:w #3\@@_find_label_aux:w
    }
}
%    \end{macrocode}
%  \end{macro}
%
%
%
% \subsection{General helper commands}
%
%
%
%  \begin{macro}{\WordSpaceAmount}
%    Produce the amount of a (fractional) word space in the current
%    font in a way that it can be used in a skip or dimen register
%    assignment. The argument specifies the fraction, e.g., \texttt{2}
%    gives two word spaces and \texttt{.5} would produce half a word
%    space.
%
%    This general helper doesn't really belong here, so should be
%    eventually moved.
%    \begin{macrocode}
\newcommand\WordSpaceAmount[1]{
  \glueexpr 
        #1\fontdimen2\the\font
  plus  #1\fontdimen3\the\font
  minus #1\fontdimen4\the\font
  \relax
}  
%    \end{macrocode}
%  \end{macro}
%
%
%    Some designs automatically add a punctuation symbol (typically a
%    period) at the end of a title, but that should only happen if the
%    title doesn't already end in a punctuation symbol.
%
%    This is achieved by setting the \cs{spacefactor} for punctuation
%    symbols (slightly) higher than \texttt{1000} and then checking the current
%    \cs{spacefactor} before trying to add the punctuation. If it is
%    \texttt{1000} or less then the title didn't end in a punctuation
%    and we can safely add one, otherwise we don't.
%
%    If \cs{nonfrenchspacing} is in force this is automatically the
%    case, but in \LaTeXe{} \cs{frenchspacing} did set the
%    \cs{spacefactor} of all punctuation symbols to \texttt{1000}
%    making them indistinguishable from other characters.
%
%    Thus, to make this work, we have to change \cs{frenchspacing}
%    which is a breaking change as it can lead to pagination
%    differences given that the word space after a punctuation gets
%    (very minimally) larger this way. However, this approach
%    was successfully used in the AMS classes for ages and it offers
%    nice design possibilities so we enable it in documents using
%    \cs{DocumentMetadata} automatically.
%
%
%  \begin{macro}{\frenchspacing,\nonfrenchspacing}
%    We give all punctuation symbols a unique \cs{sfcode} value so
%    that it is even possible to determine which punctuation was just
%    typeset.
%    \begin{macrocode}
\def\frenchspacing{\sfcode`\.1006\sfcode`\?1005\sfcode`\!1004%
  \sfcode`\:1003\sfcode`\;1002\sfcode`\,1001 }
%    \end{macrocode}
%    The same should be done for \texttt{.?!} if we want to be able to
%    distinguish those when \cs{nonfrenchspacing} is in force.  
%    \begin{macrocode}
\def\nonfrenchspacing{\sfcode`\.3002\sfcode`\?3001\sfcode`\!3000%
  \sfcode`\:2000\sfcode`\;1500\sfcode`\,1250 }
%    \end{macrocode}
%  \end{macro}
%    
%
%  \begin{macro}{\nopunct}
%    The AMS classes also offered \cs{nopunct} that could be added at
%    the end of a title and would prevent the addition of a punctuation
%    symbol.
%
%    It should have a value for \cs{spacefactor} that is not
%    used for \cs{frenchspacing} so that this special case can be
%    detected.
%    \begin{macrocode}
\cs_new_protected:Npn \nopunct {\spacefactor 1007 }
%    \end{macrocode}
%  \end{macro}
%
%
%
%  \begin{macro}{\AddPunctuation}
%    In the AMS classes this was called \cs{@addpunct}.
%
%    Note: this mechanism will fail if the text ending in a
%    punctuation has an uppercase character just before the
%    punctuation, e.g., if somebody writes \texttt{SOLUTION:}. In that
%    case \texttt{SOLUTION\cs{@}.} would be necessary!
% \changes{0.9j}{2026-057-12}{Support adding punctuation if not
%    already present  (tagging/1477)}
%    \begin{macrocode}
\cs_new_protected:Npn \AddPunctuation #1 {
  \relax\ifhmode
    \ifnum\spacefactor>\@m
      \@@_debug_typeout:n {--->~ punctuation~ '#1'~ not~ added}
    \else
      \@@_debug_typeout:n {--->~ punctuation~ '#1'~ added}
      #1
    \fi
  \fi
}
%    \end{macrocode}
%  \end{macro}
%
%
%
%
% \subsection{Templates}
%
% \subsubsection{Template types}
%
% \begin{templatetype}{heading}
%    Templates of type \texttt{heading} are used to produce headings. The
%    positional arguments are:
% \begin{verbatim}
%      1: key/val list
%      2: unnumbered?
%      3: title
%      4: toc
%      5: running
%      6: bookmark
%      7: nameref
%      8: label(s)
%      9: { subtitle } { quote }
% \end{verbatim}
%    \begin{macrocode}
\NewTemplateType{heading}{9}
%    \end{macrocode}
% \end{templatetype}
%
% \begin{templatetype}{headformat}
%    Templates of type \texttt{headformat} are used to produce heading
%    layout from the formatted heading number (if any), the heading title,
%    subtitle and quotation. The
%    positional arguments are:
% \begin{verbatim}
%      1: key/val list for document-level customizations
%      2: prefix string
%      3: formatted heading number
%      4: title
%      5: subtitle
%      6: quote
% \end{verbatim}
%    \begin{macrocode}
\NewTemplateType{headformat}{6}
%    \end{macrocode}
% \end{templatetype}
%
% \subsubsection{heading templates interfaces}
%
% We have two heading templates: display and runin.
%
%  \begin{template}{heading display}
%    The \texttt{display} template produces a display heading, i.e.,
%    one that has vertical space before and after it.
% \changes{0.9h}{2026-06-21}{Support \texttt{column-spanning} key (tagging/1436)}
%    \begin{macrocode}
\DeclareTemplateInterface{heading}{display}{9}
{
  , name            : tokenlist
  , parent-name     : tokenlist
  , reset-counter   : tokenlist
  , level           : integer = 0
%    \end{macrocode}
%    By default headings can be numbered and the numbering is
%    determined for each heading in the document individually.
% \changes{0.9h}{2026-07-04}{Support a \texttt{force-unnumbered} key
%    (tagging/1473)}
%    \begin{macrocode}
  , force-unnumbered : boolean = false
%    \end{macrocode}
%    The \key{placement} key sets default values for the keys
%    \key{start-code} and \key{final-code}.
%    \begin{macrocode}
  , placement       : choice {page , top , normal, ragged } = normal
  , column-spanning : boolean = false
  , mark-cmd        : function(1) =
  %
  % many more keys for layout settings are missing for now
  , para-indent   : choice { true , false } = false
%    \end{macrocode}
%    We use \cs{c_max_int} as a fake penalty to indicate that no
%    penalty was given in a key.
%    \begin{macrocode}
  , before-vspace : skip = 0pt
  , penalty       : integer = \c_max_int
  , after-penalty-vspace : skip = 0pt
  , after-vspace  : skip = 0pt
%    \end{macrocode}
%    The next two keys are only there to overwrite the \key{placement}
%    settings with explicit code. Thus, their default value is set up
%    by the \key{placement} key (which has a default).
%    \begin{macrocode}
  , start-code    : tokenlist =      % no default values!
  , final-code    : tokenlist =      % no default values!
%    \end{macrocode}
%    A prefix string such as \cs{@chappap} could be specified in the
%    next variable. By default is has no value.
%    \begin{macrocode}
  , prefix         : tokenlist = \NoValue
%    \end{macrocode}
%
%    \begin{macrocode}
  , heading-decls  : tokenlist = \normalfont
  , prefix-decls   : tokenlist =
  , number-decls   : tokenlist =
  , title-decls    : tokenlist =
  , subtitle-decls : tokenlist =
  , quote-decls    : tokenlist =
%    \end{macrocode}
%
%    \begin{macrocode}
  , headformat-instance : tokenlist = std
  , number-format  : function(1) = \theheading
  , contents-extra : tokenlist =
}
%    \end{macrocode}
%  \end{template}
%
%
%  \begin{template}{heading runin}
%    This template is similar to the \texttt{display} template but
%    implements a runin heading, i.e., one where the paragraph text
%    continues on the same line.
%
%    Unfortunately, we can't really use \cs{DeclareTemplateCopy} to
%    set it up because with \cs{EditTemplateDefaults} we are not able
%    to alter the setup for the \key{placement} and \key{para-indent} keys
%    as that involves changing the implementation code. Thus with
%    \cs{DeclareTemplateCopy} we can copy the interface setup but the
%    code setup still needs to be done using \cs{DeclareTemplateCode}.
%
%    \begin{macrocode}
\DeclareTemplateCopy{heading}{runin}{display}
%    \end{macrocode}
%  \end{template}
%
%
%  \subsubsection{headformat templates interfaces}
% We have three template: display, hang and runin.
%
%  \begin{template}{headformat display}
%    The \texttt{display} template produces
%    \begin{macrocode}
\DeclareTemplateInterface{headformat}{display}{6}
{
  , heading-indent    : length = 0pt
  , title-format      : function(1) = #1
  , prefix-number-sep : tokenlist = \WordSpaceAmount{1}
  , number-title-sep  : tokenlist = 20pt
}
%    \end{macrocode}
%  \end{template}
%
%  \begin{template}{headformat hang}
%    The \texttt{hang} template produces
%    \begin{macrocode}
\DeclareTemplateInterface{headformat}{hang}{6}
{
  , heading-indent    : length = 0pt
  , title-format      : function(1) = #1
  , prefix-number-sep : tokenlist = \WordSpaceAmount{1}
  , number-title-sep  : tokenlist = 1em
}
%    \end{macrocode}
%  \end{template}
%
%
%  \begin{template}{headformat runin}
%    The \texttt{runin} template produces
%    \begin{macrocode}
\DeclareTemplateInterface{headformat}{runin}{6}
{
  , heading-indent    : length = 0pt
  , title-format      : function(1) = #1
  , prefix-number-sep : tokenlist = \WordSpaceAmount{1}
  , number-title-sep  : tokenlist = 1em
}
%    \end{macrocode}
%  \end{template}
%
% \subsubsection{heading templates code}
%
%  \begin{template}{heading display}
%
%    \begin{macrocode}
\DeclareTemplateCode{heading}{display}{9}
{
  , name          = \l_@@_name_tl
  , level         = \l_@@_level_int
% next two not yet used
  , parent-name   = \l_@@_pname_tl
  , reset-counter = \l_@@_reset_cnt_tl
%    \end{macrocode}
%
% \changes{0.9h}{2026-07-04}{Support a \texttt{force-unnumbered} key
%    (tagging/1473)}
%    \begin{macrocode}
  , force-unnumbered = \l_@@_unnumbered_bool
%    \end{macrocode}
%    The \key{placement} key determines whether the heading can appear
%    anywhere (\texttt{normal}), automatically starts a new page or
%    column (\texttt{top}), or is on a page of its own (\texttt{page}.
%
%    It is usually implemented by setting \cs{l_@@_start_code_tl} and
%    \cs{l_@@_final_code_tl} (exceptions are \texttt{normal} and \texttt{ragged}).
%    These settings can be fine-tuned or
%    overwritten with the keys \key{start-code} and
%    \key{final-code}, if necessary.
%    \begin{macrocode}
  , placement     = {
        ,page   = \@@_debug_typeout:n{ A~ page~ heading }
                  \tl_set:Nn \l_@@_placement_tl { page }
        ,top    = \@@_debug_typeout:n{ A~ top~ heading }
                  \tl_set:Nn \l_@@_placement_tl { top }
        ,normal = \@@_debug_typeout:n{ A~ normal~ heading }
                  \tl_set:Nn \l_@@_placement_tl { normal }
        ,ragged = \@@_debug_typeout:n{ A~ normal~ heading~ (ragged~ style) }
                  \tl_set:Nn \l_@@_placement_tl { ragged }
                    }
%    \end{macrocode}
%    
% \changes{0.9h}{2026-06-21}{Support \texttt{column-spanning} key
%    (tagging/1436)}
%    \begin{macrocode}
  , column-spanning = \l_@@_column_spanning_bool
%    \end{macrocode}
%    
%    \begin{macrocode}
  , mark-cmd      = \@@_mark_cmd:n
%    \end{macrocode}
%    For now we make use of the legacy coding for indentation of
%    the following paragraph.
%    \begin{macrocode}
  , para-indent   = {
                      ,true  = \@afterindenttrue
                      ,false = \@afterindentfalse
                    }
  , before-vspace = \l_@@_before_skip
  , penalty       = \l_@@_penalty_int
  , after-penalty-vspace  = \l_@@_after_penalty_skip
  , after-vspace  = \l_@@_after_skip
  , start-code    = \l_@@_start_code_tl
  , final-code    = \l_@@_final_code_tl
%    \end{macrocode}
%
%    \begin{macrocode}
  , prefix        = \l_@@_typeset_prefix_tl
%    \end{macrocode}
%
%    \begin{macrocode}
  , headformat-instance = \l_@@_headformat_instance_tl
%    \end{macrocode}
%
%    \begin{macrocode}
  , heading-decls  = \l_@@_heading_decls_tl
  , prefix-decls   = \l_@@_prefix_decls_tl
  , number-decls   = \l_@@_number_decls_tl
  , title-decls    = \l_@@_title_decls_tl
  , subtitle-decls = \l_@@_subtitle_decls_tl
  , quote-decls    = \l_@@_quote_decls_tl
  , number-format  = \@@_number_format:n
  , contents-extra = \l_@@_contents_extra_tl
}
%    \end{macrocode}
%
%    \begin{macrocode}
{
%    \end{macrocode}
%
%    \begin{macrocode}
  \tl_set_eq:Nc \theheading { the \l_@@_name_tl }
%    \end{macrocode}
% We store the value of \texttt{secnumdepth} so that we can change it locally.
%    \begin{macrocode}
  \tl_set:Ne\l_@@_saved_secnumdepth_tl{\int_use:N\c@secnumdepth}
%    \end{macrocode}
%
%    \begin{macrocode}
  \@@_show_arguments:nnnnnnnnn
       {#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8}{#9}
%    \end{macrocode}
%    First evaluate any key setting done by the user in the
%    optional first argument.
%   \fmi{It would be nice if there is a variant of
%   \cs{SetTemplateKey} in which the template type and name are
%   implicit, e.g., \cs{SetCurrentTemplateKeys} because this is
%   usually what I need.}
%    \begin{macrocode}
  \tl_if_empty:oF {#1} { \SetTemplateKeys{heading}{display}{#1} }
%    \end{macrocode}
%
%    If \key{column-spanning} is requested but we are not typesetting
%    in two columns we turn it off to avoid using \cs{@topnewpage} as
%    this would be wrong. Otherwise we check the placement value and
%    adjust it if necessary.
% \changes{0.9h}{2026-06-21}{Support \texttt{column-spanning} key
%    (tagging/1436)}
%    \begin{macrocode}
  \bool_if:NT \l_@@_column_spanning_bool
       {
         \if@twocolumn
           \str_if_eq:VnF \l_@@_placement_tl {top}
             {
               \@@_debug_typeout:n {column-spanning~ requires~
                 placement=top.~ Adjusted!}
               \tl_set:Nn \l_@@_placement_tl {top}
             }
         \else
           \bool_set_false:N \l_@@_column_spanning_bool
         \fi
       }
%    \end{macrocode}
%    Based on the \key{placement} key we set up \cs{l_@@_start_code_tl}
%    and \cs{l_@@_final_code_tl}. These two variables can also be set
%    with the keys \key{start-code} and \key{final-code} in which case
%    we don't alter the definition.
%    \begin{macrocode}
  \tl_if_empty:oT \l_@@_start_code_tl
   { \str_case:VnF \l_@@_placement_tl
      {
        { page }
        { \tl_set:Nn \l_@@_start_code_tl
%    \end{macrocode}
%    Straight from the placement definition of \cs{part}.\fmi{Clearly not
%    \cs{@tempswa} and the page styles should be adjustable.}
%    \begin{macrocode}
            {
             \if@openright
               \cleardoublepage
             \else
               \clearpage
             \fi
             \thispagestyle{plain}%
             \if@twocolumn
               \onecolumn
               \@tempswatrue
             \else
               \@tempswafalse
             \fi
             \null\vfil
            }
        }
        { top }
        { \tl_set:Nn \l_@@_start_code_tl
            {
              \if@openright\cleardoublepage\else\clearpage\fi
              \thispagestyle{plain}%
              \global\@topnum\z@
            }
        }
%    \end{macrocode}
%    Ragged headings (i.e., those that leave a previous page ragged
%    bottom if they generate a page break) are produced by replacing
%    \cs{addpenalty} with a version that also adds \cs{vfil} and
%    \cs{vfilneg}. This is handled by altering
%    \cs{sec_add_penalty_with_possible_fil:n} which after use resets
%    itself to \cs{addpenalty}.
% \changes{0.9k}{2026-08-04}{Support \texttt{placement=ragged} (github/1844)}
%    \begin{macrocode}
        { ragged }
        { \cs_set_eq:NN \sec_add_penalty_with_possible_fil:n 
                        \sec_add_penalty_with_fil:n
        }
      }
      { \tl_clear:N \l_@@_start_code_tl }
   }
%
  \tl_if_empty:oT \l_@@_final_code_tl
   { \str_case:VnF \l_@@_placement_tl
      {
        { page }
        { \tl_set:Nn \l_@@_final_code_tl
            {
              \vfil\newpage
              \if@twoside
                \if@openright
                  \null
                  \thispagestyle{empty}%
                \newpage
                \fi
              \fi
              \if@tempswa
                \twocolumn
              \fi
            }
        }
      }
      { \tl_set:Nn  \l_@@_final_code_tl { \@afterheading } }
   }
%    \end{macrocode}
%    Then we set up the penalty to use (might be given as a key value).
%    \begin{macrocode}
  \@@_determine_penalty:
%    \end{macrocode}
%
%    \begin{macrocode}
  \@@_determine_number_typesetting:N #2
%    \end{macrocode}
%    Next comes the vertical spacing and penalty before the heading. This includes
%    running \cs{l_@@_start_code_tl} if it contains any code, e.g., to
%    start a new page.
%    \begin{macrocode}
  \@@_vertical_before_spacing:
%    \end{macrocode}
% We are in vmode now and here is the point where we (with tagging) can close a previous Sect
% structure and open the new one.
%    \begin{macrocode}
\UseTaggingSocket{sec/end}{\int_use:N\l_@@_level_int}
\UseTaggingSocket{sec/begin}
  {{\int_use:N\l_@@_level_int}{tag=\UseStructureName{sec/\int_use:N\l_@@_level_int}}}
%    \end{macrocode}
%    Up to this point everything is identical for both display and
%    runin headings. But from now on they have their own code.
%    We have dealt with argument \#1 and \#2 so now we can unbundle
%    argument \#9 so that it is easier to process downstream
%    \begin{macrocode}
  \@@_debug_typeout:n{use~ 'headformat'~instance:~
                       \l_@@_headformat_instance_tl }
  \use:e {
%    \end{macrocode}
%    
%    As long as we don't have a decent interface for the OR we have to
%    use \cs{@topnewpage} for getting spanning headings (which means
%    we are really using a top float box. That in turn means we have
%    to get all the vertical spacing and so inside this box so there
%    is a lot of back and forth based on the value of
%    \cs{l_@@_column_spanning_bool} for now.
% \changes{0.9h}{2026-06-21}{Support \texttt{column-spanning} key
%    (tagging/1436)}
%    \begin{macrocode}
    \bool_if:NT \l_@@_column_spanning_bool
         { \exp_not:n {
             \@topnewpage [
             \dim_compare:nNnF{\l_@@_after_penalty_skip}={0pt}
                 { \vspace*    \l_@@_after_penalty_skip }
           }
         }
    \UseInstance{headformat} { \l_@@_headformat_instance_tl }
                { \exp_not:o \UnusedTemplateKeys }
                { \exp_not:o { \l_@@_typeset_prefix_tl } }
                { \exp_not:o { \l_@@_typeset_number_tl } }
                { \exp_not:n { #3 } }
                { \exp_not:o { \use_i:nn  #9 } }
                { \exp_not:o { \use_ii:nn  #9 } }
%    \end{macrocode}
%    
% \changes{0.9h}{2026-06-21}{Support \texttt{column-spanning} key
%    (tagging/1436)}
%    \begin{macrocode}
    \bool_if:NT \l_@@_column_spanning_bool
         {
           \skip_vertical:N \l_@@_after_skip
%    \end{macrocode}
%    Add the final vspace after the heading and close the
%    \cs{@topnewpage} which has an optional argument.
%    \begin{macrocode}
           ]
         }
  }
 %
% --- handle marks, toc-entry, bookmark, nameref, and label
%
  \@@_handle_marks_etc:nnnnn {#4}{#5}{#6}{#7}{#8}
%
% --- post-heading handling (vertical)
%    \end{macrocode}
% Restore \texttt{secnumdepth}
%    \begin{macrocode}
  \int_gset:Nn\c@secnumdepth{\l_@@_saved_secnumdepth_tl}
  \par 
%    \end{macrocode}
%    If we have a spanning heading then the vertical skip is handled
%    inside \cs{@topnewpage} and not here.
% \changes{0.9h}{2026-06-21}{Support \texttt{column-spanning} key
%    (tagging/1436)}
%    \begin{macrocode}
  \bool_if:NF \l_@@_column_spanning_bool
       {
         \nobreak
         \skip_vertical:N \l_@@_after_skip
       }
% --- prepare next paragraph (defaults to \cs{@afterheading}
%
  \l_@@_final_code_tl
%
  \ignorespaces
}
%    \end{macrocode}
%  \end{template}
%
%
%  \begin{macro}{\sec_add_penalty_with_fil:n,
%                \sec_add_penalty_with_possible_fil:n}
%    The command \cs{sec_add_penalty_with_fil:n} adds a penalty
%    surrounded by stretchable glue like the plain \TeX{}
%    \cs{filbreak} command. After use it sets
%    \cs{sec_add_penalty_with_possible_fil:n} back to \cs{addpenalty}.
%
%    They have public names so that they can be used in other heading
%    templates outside of this module.
% \changes{0.9k}{2026-08-04}{Support \texttt{placement=ragged} (github/1844)}
%    \begin{macrocode}
\cs_new_protected:Npn \sec_add_penalty_with_fil:n #1 {
  \@@_debug_typeout:n{apply~ ragged~ bottom~ fil}
%    \end{macrocode}
%    Next code is straight from \cs{addpenalty} except that the
%    generated \cs{penalty} is surrounded by \cs{vfil} and \cs{vfilneg}.
%    \begin{macrocode}
  \addpenaltywithfil { #1 }
%    \end{macrocode}
%    Then reset so that next time \cs{addpenalty} is used again.
%    \begin{macrocode}
  \cs_set_eq:NN
    \sec_add_penalty_with_possible_fil:n
    \addpenalty
}
%    \end{macrocode}
%    By default \cs{sec_add_penalty_with_possible_fil:n} is the same
%    as \cs{addpenalty}. If you set it to
%    \cs{sec_add_penalty_with_fil:n} then it uses the "filbreak"
%    mechanism and afterwards resets itself to its default definition.
%    \begin{macrocode}
\cs_set_eq:NN
  \sec_add_penalty_with_possible_fil:n
  \addpenalty
%    \end{macrocode}
%  \end{macro}
%
%
%
%  \begin{macro}{\__kernel_add_penalty:n,
%                \addpenalty,\addpenaltywithfil}
%    
%    Next code is for inclusion in the kernel.  It is basically the
%    code from \LaTeX{}'s \cs{addpenalty} but with a slightly
%    different argument so that you have to supply
%    \verb=\penalty #1\relax= to mimic \cs{addpenalty} and
%    \verb=\vfil \penalty #1\vfilneg= to produce a penalty generating
%    a filbreak, i.e., a break where the previous page is ragged bottom.
%    \begin{macrocode}
\cs_new_protected:Npn \__kernel_add_penalty:n #1 {
%    \end{macrocode}
%    Don't add anything at the start of a minipage or when
%    \texttt{@nobreak} is set (i.e., directly after a heading).
%    \begin{macrocode}
  \mode_if_horizontal:T
    { \mode_if_inner:TF { \@LRmoderr }{ \par } }  
  \legacy_if:nF { @minipage }
    { \legacy_if:nF { @nobreak }
        {
%    \end{macrocode}
%    Do everything in a group so that the temp variables are restored
%    afterwards in case they are used at the outside.
%    \begin{macrocode}
          \group_begin:
%    \end{macrocode}
%    The rest is also from \cs{addpenalty} except that we have to give
%    \cs{penalty} explicitly as part of the argument.
%  
%    If there wasn't any previous skip or only a zero-sized one simply
%    set the penalty.
%    \begin{macrocode}
          \skip_set_eq:NN \l_tmpa_skip \tex_lastskip:D
          \dim_compare:nNnTF \l_tmpa_skip = \c_zero_dim
            { #1 }
%    \end{macrocode}
%    Otherwise copy the last skip value also into \cs{l_tmpb_skip}
%    using \TeX's fast direct assignment.
%    \begin{macrocode}
            { 
              \skip_set_eq:NN \l_tmpb_skip \l_tmpa_skip
%    \end{macrocode}
%    Then add to it the current \cs{prevdepth} unless it is
%    \texttt{-1000pt} (which means it should be suppressed) or if it
%    is unusually large, in which case add \cs{maxdepth} instead. We
%    remember that value because it will be reused below.
%    \begin{macrocode}
              \dim_set:Nn \l_tmpa_dim
                 {
                   \dim_compare:nNnTF \prevdepth > \maxdepth
                     \maxdepth
                     { \dim_compare:nNnTF \prevdepth = { -1000pt }
                          \c_zero_dim
                          \prevdepth
                     }
                 }
              \skip_add:Nn \l_tmpb_skip \l_tmpa_dim
%    \end{macrocode}
%    This is the amount we have to back up in order to position us
%    vertically where the bottom of the page would be if a natural
%    break would happen.
%    \begin{macrocode}
              \vskip -\l_tmpb_skip
%    \end{macrocode}
%    That is then the point where we have to add the explicit penalty
%    or the filbreak code.
%    \begin{macrocode}
              #1
%    \end{macrocode}
%    After the penalty (and after a possible \cs{vfilneg}) we have to
%    readd what we back up but that isn't as trivial as one might
%    think.
%       
%    First we have to move forward by whatever amount we backed up due
%    to \cs{prevdepth} because going forward the \cs{prevdepth} will
%    be zero.   
%    \begin{macrocode}
              \dim_compare:nNnF \l_tmpa_dim = \c_zero_dim
                { \vskip \l_tmpa_dim }
%    \end{macrocode}
%    Finally we have to reinsert what we saved as \cs{lastskip},
%    because that is what any following \cs{addvspace} should see to
%    make its calculations from.
%    \begin{macrocode}
              \vskip \l_tmpa_skip
            }
          \group_end:
        }
    }
}
%    \end{macrocode}
%    Reimplement \cs{addpenalty} using the above macro:
%    \begin{macrocode}
\cs_set_protected:Npn \addpenalty #1 {
  \__kernel_add_penalty:n { \penalty #1 \scan_stop: }
}
%    \end{macrocode}
%    And a new command to add a penalty with some \cs{vfil} around
%    it. They cancel each other if no break is taken.
%    \begin{macrocode}
\cs_new_protected:Npn \addpenaltywithfil #1 {
  \__kernel_add_penalty:n { \vfil \penalty #1 \vfilneg }
}
%    \end{macrocode}
%    
%  \end{macro}
%
%
%
%
%
%  \begin{macro}{\if@openright}
%
%    \begin{macrocode}
\AddToHook{begindocument}{
  \ifcsname if@openright\endcsname
  \else
%    \end{macrocode}
%    Need to hide this a little if it is in fact already defined!
%    \begin{macrocode}
    \expandafter\newif\csname if@openright\endcsname
  \fi
}
%    \end{macrocode}
%  \end{macro}
%
%  \begin{template}{heading runin}
%    The \texttt{runin} template is very similar to the
%    \texttt{display} one.
%    \begin{macrocode}
\DeclareTemplateCode{heading}{runin}{9}
 {
  , name           = \l_@@_name_tl
  , level          = \l_@@_level_int
% next two not yet used
  , parent-name    = \l_@@_pname_tl
  , reset-counter  = \l_@@_reset_cnt_tl
%    \end{macrocode}
%
% \changes{0.9h}{2026-07-04}{Support a \texttt{force-unnumbered} key
%    (tagging/1473)}
%    \begin{macrocode}
  , force-unnumbered = \l_@@_unnumbered_bool
%    \end{macrocode}
%
%    It wouldn't make sense to have page placement with a runin heading since
%    there would be nothing to run into.
%    \begin{macrocode}
  , placement      = {
         page   = \typeout{ ^^JA~ runin~ page~ placement~ heading~makes~no~sense
                            (top~used)}
                  \tl_set:Nn \l_@@_placement_tl { top }
        ,top    = \@@_debug_typeout:n{ A~ top~ heading }
                  \tl_set:Nn \l_@@_placement_tl { top }
        ,normal = \@@_debug_typeout:n{ A~ normal~ heading }
                  \tl_set:Nn \l_@@_placement_tl { normal }
        ,ragged = \@@_debug_typeout:n{ A~ normal~ heading~ (ragged~ style) }
                  \tl_set:Nn \l_@@_placement_tl { ragged }
                    }
%    \end{macrocode}
%    
% \changes{0.9h}{2026-06-21}{Support \texttt{column-spanning} key
%    (tagging/1436)}
%    \begin{macrocode}
  , column-spanning = \l_@@_column_spanning_bool
%    \end{macrocode}
%    
%    \begin{macrocode}
  , mark-cmd       = \@@_mark_cmd:n
%    \end{macrocode}
%    In a runin heading you can't set up paragraph indentation of the
%    following paragraph (since that one is \enquote{run in}. But we
%    accept the key and just spit out a warning.
%    \ufi{this types out messages for all run-in headers! Therefore disabled for now}
%    \begin{macrocode}
  , para-indent    =  {
                       ,true  = %\typeout{para-indent~ setting~ ignored}
                       ,false = %\typeout{para-indent~ setting~ ignored}
                      }
  , before-vspace  = \l_@@_before_skip
  , penalty        = \l_@@_penalty_int
%    \end{macrocode}
%    Next key makes no sense either in a runin heading and is not
%    used.\fmi{Revise and separate the two templates better}
%    \begin{macrocode}
  , after-penalty-vspace  = \l_@@_after_penalty_skip
  , after-vspace   = \l_@@_after_skip
  , start-code     = \l_@@_start_code_tl
  , final-code     = \l_@@_final_code_tl
%    \end{macrocode}
%
%    \begin{macrocode}
  , prefix        = \l_@@_typeset_prefix_tl
%    \end{macrocode}
%
%    \begin{macrocode}
  , headformat-instance = \l_@@_headformat_instance_tl
%    \end{macrocode}
%
%    \begin{macrocode}
  , heading-decls  = \l_@@_heading_decls_tl
  , prefix-decls   = \l_@@_prefix_decls_tl
  , number-decls   = \l_@@_number_decls_tl
  , title-decls    = \l_@@_title_decls_tl
  , subtitle-decls = \l_@@_subtitle_decls_tl
  , quote-decls    = \l_@@_quote_decls_tl
%    \end{macrocode}
%
%    \begin{macrocode}
  , number-format  = \@@_number_format:n
  , contents-extra = \l_@@_contents_extra_tl
}
{
  \@@_show_arguments:nnnnnnnnn
       {#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8}{#9}
%    \end{macrocode}
% store the value of \texttt{secnumdepth} so that we can change it locally.
%    \begin{macrocode}
  \tl_set:Ne\l_@@_saved_secnumdepth_tl{\int_use:N\c@secnumdepth}
%    \end{macrocode}
% define \cs{theheading}
%    \begin{macrocode}
  \tl_set_eq:Nc \theheading { the \l_@@_name_tl }
  \tl_if_empty:oF {#1} { \SetTemplateKeys{heading}{runin}{#1} }
%    \end{macrocode}
%    For now we don't support column-spanning in this template.
% \changes{0.9h}{2026-06-21}{Support \texttt{column-spanning} key
%    (tagging/1436)}
%    \begin{macrocode}
  \bool_if:NT \l_@@_column_spanning_bool
    {
        \@@_debug_typeout:n {column-spanning~ is~
              not~ (yet)~ supported~ for~ runin~ headings!}
        \bool_set_false:N \l_@@_column_spanning_bool
    }
%    \end{macrocode}
%
%    \begin{macrocode}
  \tl_if_empty:oT \l_@@_start_code_tl
   {
    \str_case:Vn \l_@@_placement_tl
      {
        { top }   { \tl_set:Nn \l_@@_start_code_tl {\clearpage } }
%    \end{macrocode}
%    
% \changes{0.9k}{2026-08-04}{Support \texttt{placement=ragged} (github/1844)}
%    \begin{macrocode}
        { ragged }
        { \cs_set_eq:NN \sec_add_penalty_with_possible_fil:n 
                        \sec_add_penalty_with_fil:n
        }   
      }
%    \end{macrocode}
%    All other cases want an empty \cs{l_@@_start_code_tl} so nothing
%    to do.
%    \begin{macrocode}
%      { \tl_clear:N \l_@@_start_code_tl }
   }
%
%    \end{macrocode}
%    Nothing at all to do (for now) for \cs{l_@@_final_code_tl}, it
%    should by default be empty in all heading placement. But maybe
%    we end up supporting further placements, so~\ldots
%    \begin{macrocode}
%  \tl_if_empty:oT \l_@@_final_code_tl
%   { \str_case:VnF \l_@@_placement_tl
%      {
%        { top } { \tl_clear:N \l_@@_final_code_tl }
%      }
%      { \tl_clear:N \l_@@_final_code_tl }
%   }
%    \end{macrocode}
%
%    \begin{macrocode}
  \@@_determine_penalty:
  \@@_determine_number_typesetting:N #2
  \@@_vertical_before_spacing:
%    \end{macrocode}
% We are in vmode now and here is the point where we (with tagging) can close a previous Sect
% structure and open the new one. We also have to initialize the change in the paratagging here
% as run-in titles typeset the heading in \cs{everypar}.
%    \begin{macrocode}
  \UseTaggingSocket{sec/end}{\int_use:N\l_@@_level_int}
  \UseTaggingSocket{sec/begin}
    {{\int_use:N\l_@@_level_int}{tag=\UseStructureName{sec/\int_use:N\l_@@_level_int}}}
  \UseTaggingSocket{sec/title/init}{\int_use:N\l_@@_level_int}
  \def \@svsechd {
      \@@_debug_typeout:n{use~ 'headformat'~instance:~
                          \l_@@_headformat_instance_tl }
      \use:e {
        \UseInstance{headformat} { \l_@@_headformat_instance_tl }
                 { \exp_not:o \UnusedTemplateKeys }
                 { \exp_not:o { \l_@@_typeset_prefix_tl } }
                 { \exp_not:o { \l_@@_typeset_number_tl } }
                 { \exp_not:n { #3 } }
                 { \exp_not:o { \use_i:nn  #9 } }
                 { \exp_not:o { \use_ii:nn  #9 } }
      }
      \@@_handle_marks_etc:nnnnn {#4}{#5}{#6}{#7}{#8}
%    \end{macrocode}
% Restore \texttt{secnumdepth}
%    \begin{macrocode}
      \int_gset:Nn\c@secnumdepth{\l_@@_saved_secnumdepth_tl}
  }
%
  \@nobreakfalse
  \global\@noskipsectrue
  \everypar{%
    \if@noskipsec
       \global\@noskipsecfalse
       {\setbox\z@\lastbox}
       \clubpenalty\@M
%FMi group is in headformat
%      \begingroup
       \@svsechd
%      \endgroup
       \unskip
%    \end{macrocode}
%  This tagging socket starts the \enquote{paragraph} after the run-in heading
%    \begin{macrocode}
       \UseTaggingSocket{sec/title/split}
       \skip_horizontal:N \l_@@_after_skip
    \else
      \clubpenalty \@clubpenalty
      \everypar{}%
    \fi
  }
%    \end{macrocode}
% --- prepare next paragraph (does nothing by default)
%    \begin{macrocode}
  \l_@@_final_code_tl
%
  \ignorespaces
}
%    \end{macrocode}
%  \end{template}
%
% \subsubsection{headformat templates code}
%
%  \begin{template}{headformat display}
%  This template creates a headformat where the number is on a line on its own.
%    \begin{macrocode}
\DeclareTemplateCode{headformat}{display}{6} % args: keys,prefix,number,title,subtitle,quotation
 {
  , heading-indent    = \l_@@_heading_indent_dim
  , title-format      = \@@_title_format:n
  , prefix-number-sep = \l_@@_prefix_number_sep_tl
  , number-title-sep  = \l_@@_number_title_sep_tl
 }
 {
  \@@_show_arguments:nnnnnn {#1}{#2}{#3}{#4}{#5}{#6}
%    \end{macrocode}
%    First evaluate any key setting done by the user (normally
%    supplied from the main heading instance.
%    \begin{macrocode}
  \tl_if_empty:oF {#1} { \SetTemplateKeys{headformat}{display}{#1} }
%    \end{macrocode}
%
%    \begin{macrocode}
  \group_begin:
  \UseTaggingSocket{sec/title/begin}{{\int_use:N\l_@@_level_int}{#4}}
%    \end{macrocode}
% \changes{0.9f}{2026-05-23}{Removed \cs{normalcolor} as it adds a break point 
%  and prevents color changes tagging/1215}
%  TODO: revisit if \cs{normalcolor} is needed, if yes, use as
%  \verb+\SaveLastSkip\normalcolor\RestoreLastSkip+.
%    \begin{macrocode}
    \normalfont 
    \interlinepenalty \@M
    \l_@@_heading_decls_tl{}
%    \end{macrocode}
%   If there is a number and so a prefix, the link target should be before the number.
%   We use for now the same place in the unnumbered case.
%   TODO: If we put the target here we do not know the height of the line and the
%   target is perhaps not high enough. And for unnumbered chapter it is perhaps too high.
%   Check!
%    \begin{macrocode}
    \bool_if:NTF \l_@@_unnumbered_bool
      {
        \dim_compare:nNnTF  \l_@@_heading_indent_dim < \c_zero_skip
          {
            \skip_horizontal:N \l_@@_heading_indent_dim
            \MakeLinkTarget[\l_@@_name_tl]{}
          }
          {
            \MakeLinkTarget[\l_@@_name_tl]{}\skip_horizontal:N \l_@@_heading_indent_dim
          }
      }
      {
        \dim_compare:nNnTF  \l_@@_heading_indent_dim < \c_zero_skip
          {
            \skip_horizontal:N \l_@@_heading_indent_dim
            \MakeLinkTarget{\l_@@_name_tl}
          }
          {
            \MakeLinkTarget{\l_@@_name_tl}\skip_horizontal:N \l_@@_heading_indent_dim
          }
        \IfNoValueF{#2}
          {    
            { \l_@@_prefix_decls_tl #2 }
            \nobreak
            \skip_horizontal:n { \l_@@_prefix_number_sep_tl }
          }
        \l_@@_number_decls_tl
        #3
        \par\nobreak
        \skip_vertical:n { \l_@@_number_title_sep_tl }
      }
    \l_@@_title_decls_tl
%    \end{macrocode}
%    \fmi{probably better to use a format:n and drop these two code
%    variables even though they are used by titlesec}
%    \begin{macrocode}
    \@@_title_format:n {#4}
    \par
    \UseTaggingSocket{sec/title/end}
  \group_end:
 }
%    \end{macrocode}
%  \end{template}
%
%  \begin{template}{headformat hang}
% This template creates a heading with a hanging number.
%    \begin{macrocode}
\DeclareTemplateCode{headformat}{hang}{6} % args: keys,prefix,number,title,subtitle,quotation
 {
  , heading-indent    = \l_@@_heading_indent_dim
  , title-format      = \@@_title_format:n
  , prefix-number-sep = \l_@@_prefix_number_sep_tl
  , number-title-sep  = \l_@@_number_title_sep_tl
 }
 {
  \@@_show_arguments:nnnnnn {#1}{#2}{#3}{#4}{#5}{#6}
%    \end{macrocode}
%    First evaluate any key setting done by the user (normally
%    supplied from the main heading instance.
%    \begin{macrocode}
  \tl_if_empty:oF {#1} { \SetTemplateKeys{headformat}{hang}{#1} }
%    \end{macrocode}
%
%    \begin{macrocode}
  \group_begin:
    \UseTaggingSocket{sec/title/init}{\int_use:N\l_@@_level_int}
%    \end{macrocode}
% \changes{0.9f}{2026-05-23}{Removed \cs{normalcolor} as it adds a break point 
%  and prevents color changes tagging/1215}
%    \begin{macrocode}
    \normalfont 
    \interlinepenalty \@M
    \l_@@_heading_decls_tl{}
%    \end{macrocode}
% The link target should be at the left text margin, or, if the section
% is moved into the margin, at the left of the number.
%    \begin{macrocode}
    \bool_if:NTF \l_@@_unnumbered_bool
      {
        \tl_set:Nn\l_@@_tmpa_tl
         {
          \dim_compare:nNnTF  \l_@@_heading_indent_dim < \c_zero_skip
            {
                \skip_horizontal:N \l_@@_heading_indent_dim \MakeLinkTarget[\l_@@_name_tl]{}
            }
            {
                \MakeLinkTarget[\l_@@_name_tl]{}
                \skip_horizontal:N \l_@@_heading_indent_dim
            }
         }
      }
      {
       \tl_set:Nn \l_@@_tmpa_tl
        {
          \dim_compare:nNnTF  \l_@@_heading_indent_dim < \c_zero_skip
              {
                \skip_horizontal:N \l_@@_heading_indent_dim  \MakeLinkTarget{\l_@@_name_tl}
              }
              {
                \MakeLinkTarget{\l_@@_name_tl}\skip_horizontal:N \l_@@_heading_indent_dim
              }
          \IfNoValueF{#2}
              {    
                { \l_@@_prefix_decls_tl #2 }
                \nobreak
                \skip_horizontal:n { \l_@@_prefix_number_sep_tl }
              }
          { \l_@@_number_decls_tl #3 }
          \skip_horizontal:n { \l_@@_number_title_sep_tl }
        }
       }
     \UseTaggingSocket{sec/title/hang}
       {{\int_use:N\l_@@_level_int}\l_@@_unnumbered_bool{\l_@@_tmpa_tl}{#4}}
       {
        \@hangfrom
          {
           \l_@@_tmpa_tl
          }
       }
    \l_@@_title_decls_tl
%    \end{macrocode}
%    \fmi{probably better to use a format:n and drop these two code
%    variables even though they are used by titlesec}
%    \begin{macrocode}
    \@@_title_format:n {#4}
    \par
  \group_end:
 }
%    \end{macrocode}
%  \end{template}
%
%
%  \begin{template}{headformat runin}
% This template creates a heading with a run-in title.
% Arguments are key-value, number, title, subtitle, quotation.
%    \begin{macrocode}
\DeclareTemplateCode{headformat}{runin}{6} % args: keys,prefix,number,title,subtitle,quotation
 {
  , heading-indent    = \l_@@_heading_indent_dim
  , title-format      = \@@_title_format:n
  , prefix-number-sep = \l_@@_prefix_number_sep_tl
  , number-title-sep  = \l_@@_number_title_sep_tl
 }
 {
  \@@_show_arguments:nnnnnn {#1}{#2}{#3}{#4}{#5}{#6}
%    \end{macrocode}
%    First evaluate any key setting done by the user (normally
%    supplied from the main heading instance.
%    \begin{macrocode}
  \tl_if_empty:oF {#1} { \SetTemplateKeys{headformat}{hang}{#1} }
%    \end{macrocode}
%
%    \begin{macrocode}
  \group_begin:
%    \end{macrocode}
%
% \changes{0.9f}{2026-05-23}{Removed \cs{normalcolor} as it adds a break point 
%  and prevents color changes tagging/1215}
%    \begin{macrocode}
    \normalfont 
%    \end{macrocode}
%    \fmi{Setting \cs{interlinepenalty} makes little sense I think
%    (but that's the way it was in \LaTeXe)}
%    \begin{macrocode}
    \interlinepenalty \@M
    \l_@@_heading_decls_tl{}
%    \end{macrocode}
% We must avoid that the sep between number and title is used in the unnumbered case.
% So we test with the boolean.
%    \begin{macrocode}
    \bool_if:NTF \l_@@_unnumbered_bool
      {
        \dim_compare:nNnTF  \l_@@_heading_indent_dim < \c_zero_skip
         {
           \skip_horizontal:N \l_@@_heading_indent_dim
           \MakeLinkTarget[\l_@@_name_tl]{}
         }
         {
           \MakeLinkTarget[\l_@@_name_tl]{}\skip_horizontal:N \l_@@_heading_indent_dim
         }
      }
      {
         \dim_compare:nNnTF  \l_@@_heading_indent_dim < \c_zero_skip
         {
           \skip_horizontal:N \l_@@_heading_indent_dim \MakeLinkTarget{\l_@@_name_tl}
         }
         {
           \MakeLinkTarget{\l_@@_name_tl}\skip_horizontal:N \l_@@_heading_indent_dim
         }
         {
           \UseTaggingSocket{sec/title/number}{\int_use:N\l_@@_level_int}
             {
               \IfNoValueF{#2}
                 {    
                   { \l_@@_prefix_decls_tl #2 }
                   \nobreak
                   \skip_horizontal:n { \l_@@_prefix_number_sep_tl }
                 }
                 \l_@@_number_decls_tl
                 #3
             }
         }
         \skip_horizontal:n { \l_@@_number_title_sep_tl }
      }
%    \end{macrocode}
%
%    \begin{macrocode}
    \l_@@_title_decls_tl
    \@@_title_format:n {#4}
  \group_end:
}
%    \end{macrocode}
%  \end{template}
%
% \subsubsection{Internal commands used by the template code}
%
%  \begin{macro}{\@@_determine_penalty:}
%
%    \begin{macrocode}
\cs_new:Npn \@@_determine_penalty: {
%    \end{macrocode}
%    If a penalty was specified use it, otherwise use \cs{@secpenalty}.
%    \begin{macrocode}
  \int_compare:nNnT \l_@@_penalty_int = \c_max_int
    { \int_set:Nn \l_@@_penalty_int \@secpenalty }
}
%    \end{macrocode}
%  \end{macro}

%  \begin{macro}{\@@_determine_number_typesetting:N}
%
%    \begin{macrocode}
\cs_new:Npn \@@_determine_number_typesetting:N #1 {
%    \end{macrocode}
%    If \key{force-unnumbered} was set to true (i.e.,
%    \cs{l_@@_unnumbered_bool}) we don't do numbering.
%    If that is not the case then  using or suppressing a heading
%    number depends on the heading level
%    compared to the document value of \cs{c@secnumdepth}. If that
%    doesn't suppress the number then an explicit key or a star form
%    might still have suppressed it.
% \changes{0.9h}{2026-07-04}{Support a \texttt{force-unnumbered} key
%    (tagging/1473)}
%    \begin{macrocode}
  \bool_if:NF \l__head_unnumbered_bool
     {
       \bool_set:Nn \l_@@_unnumbered_bool
        { \bool_lazy_or_p:nn
          { \int_compare_p:nNn \l_@@_level_int > \c@secnumdepth }
          { \bool_if_p:N #1 }
        }
     }
%    \end{macrocode}
%    If we aren't producing a heading with a number we set
%    \cs{c@secnumdepth} to a low number (it is reset at the end of the template
%    code)
%    \begin{macrocode}
  \bool_if:NTF \l_@@_unnumbered_bool
    {
      \int_gset:Nn\c@secnumdepth{-99}
%    \end{macrocode}
%    and we set \cs{l_@@_typeset_number_tl} to do nothing.
%    \begin{macrocode}
      \tl_clear:N \l_@@_typeset_number_tl
    }
%    \end{macrocode}
%    Otherwise the heading counter is incremented and a formatted
%    version of the number plus any following (or preceding) space is
%    stored in \cs{l_@@_typeset_number_tl}.
%    We use the kernel version of \cs{refstepcounter} as anchors are handled elsewhere.
%    \begin{macrocode}
    {
      \@kernel@refstepcounter{ \l_@@_name_tl }
      \protected@edef \l_@@_typeset_number_tl
        {
          \@@_number_format:n { \l_@@_name_tl }
        }
    }
}
%    \end{macrocode}
%  \end{macro}



%  \begin{macro}{\@@_vertical_before_spacing:}
%
%    \begin{macrocode}
\cs_new:Npn \@@_vertical_before_spacing: {
  \tl_if_blank:VTF \l_@@_start_code_tl
     {
       \if@noskipsec \leavevmode \fi
       \par
       \if@nobreak
         \everypar{}
       \else
%    \end{macrocode}
%    Normally the penalty is added with \cs{addpenalty} but in some
%    cases (\texttt{placement=ragged}) we want to use a variant of
%    \cs{filbreak} instead. So we use
%    \cs{sec_add_penalty_with_possible_fil:n} which is either equal to
%    \cs{addpenalty} or  to \cs{sec_add_penalty_with_fil:n} depending
%    on the setup.
% \changes{0.9k}{2026-08-04}{Support \texttt{placement=ragged} (github/1844)}
%    \begin{macrocode}
         \sec_add_penalty_with_possible_fil:n
            \l_@@_penalty_int
         \addvspace  \l_@@_before_skip
%    \end{macrocode}
% The \cs{vspace*} inserts a rule, we insert therefore the
% skip only if it is different to zero.
%    \begin{macrocode}
         \dim_compare:nNnF{\l_@@_after_penalty_skip}={0pt}
          { \vspace*    \l_@@_after_penalty_skip }
       \fi
     }
     {
       \l_@@_start_code_tl
%    \end{macrocode}
%    If \cs{l_@@_start_code_tl} holds code, we assume that it handles
%    pagination, e.g., a \cs{clearpage}, etc. We therefore only add
%    the skip that would follow the penalty.
%
%    And we do nothing at all when we have a spanning heading. Then
%    this vspace is done inside \cs{@topnewpage}.
% \changes{0.9h}{2026-06-21}{Support \texttt{column-spanning} key
%    (tagging/1436)}
%    \begin{macrocode}
       \bool_if:NF \l_@@_column_spanning_bool
            {
              \dim_compare:nNnF{\l_@@_after_penalty_skip}={0pt}
                  { \vspace*    \l_@@_after_penalty_skip }
            }
     }
}
%    \end{macrocode}
%  \end{macro}
%
% \begin{macro}{\addcontentslinebookmark,\addcontentslinebookmarkOff,
% \addcontentslinebookmarkOn}
% We want to be able to control bookmarks independently from the toc entries,
% and also want to disable a bookmark by setting it to empty. For this we need
% some command to handle the bookmark command.
%    \begin{macrocode}
\newcommand\addcontentslinebookmark[3]{}
\newcommand\addcontentslinebookmarkOff{}
\newcommand\addcontentslinebookmarkReset{}
\providecommand\texorpdfstring[2]{#1}
%    \end{macrocode}
% This can go once hyperref is updated (ufi,2026-04-21):
%    \begin{macrocode}
\AddToHook{package/hyperref/after}
 {
  \RenewCommandCopy\addcontentslinebookmark\Hy@addcontentsline@addbookmark
  \renewcommand\addcontentslinebookmarkOff
   {
    \ifHy@bookmarks
     \let\addcontentslinebookmarkReset\Hy@bookmarkstrue
    \else
      \let\addcontentslinebookmarkReset\relax
    \fi
    \Hy@bookmarksfalse
   }
 }
%    \end{macrocode}
% \end{macro}
%
%  \begin{macro}{\@@_handle_marks_etc:nnnnn}
% Arg 1: toc entry, arg 2: mark, arg 3: bookmark, arg 4: nameref, arg 5: label code
%    \begin{macrocode}
\cs_new:Npn \@@_handle_marks_etc:nnnnn #1#2#3#4#5 {
%
  \tl_set:Nn\@currentlabelname{#4}
  \IfBlankF {#2}
     { \@@_mark_cmd:n { #2 } }
  \IfBlankTF {#1}
%    \end{macrocode}
% If the toc entry is empty the bookmarks must be set without \cs{addcontentsline}
%    \begin{macrocode}
    {
      \IfBlankF{#3}
       {
        \addcontentslinebookmark{toc}{\l__head_name_tl}
          {
            \bool_if:NF \l_@@_unnumbered_bool
              {
                \protect\numberline{ \use:c{ the \l_@@_name_tl } }
              }
            #3
          }
       }
    }
    {
%    \end{macrocode}
% If the bookmark entry is empty we must disable the bookmarks locally
% before the \cs{addcontentsline} and reenable afterwards. We do not
% check if they are already disabled, perhaps later.
%    \begin{macrocode}
     \IfBlankT{#3}{\addcontentslinebookmarkOff}
     \addcontentsline{toc}{ \l_@@_name_tl }
        {
          \bool_if:NF \l_@@_unnumbered_bool
            {
              \protect\numberline{ \use:c{ the \l_@@_name_tl } }
            }
%    \end{macrocode}
% We use \cs{texorpdfstring} to separate toc and bookmark text.
%    \begin{macrocode}
          \texorpdfstring{#1}{#3}
        }
      \addcontentslinebookmarkReset
    }
%    \end{macrocode}
%    Some headings (like \cs{chapter}) also want to write stuff to
%    other contents files like \texttt{.lot} or
%    \texttt{.lof}.\fmi{perhaps this should have a hook for packages}
%    \begin{macrocode}
  \l_@@_contents_extra_tl
%    \end{macrocode}
%    We can always run the label code (it might be empty)
%    \begin{macrocode}
  \@@_debug_typeout:n{--->~label(s):~ \exp_not:n{#5}}
  #5
}
%    \end{macrocode}
%  \end{macro}
%
%
%
%
% \subsection{Support for legacy classes and packages}
%
%   If we define heading commands in the kernel (or in the tagging
%    code) using
% \begin{verbatim}
%   \DeclareDocumentCommand \section {s ={shorttitle}o m}
%       { \ParseLaTeXeHeading {section} {#1} {#2} {#3} }
% \end{verbatim}
%   then this gets overwritten by every class right now.
%
%    If we redeclare them after the class was loaded then
%    we overwrite the layout of legacy classes (done, for example, with
%    \cs{@startsection}). New classes that use the above interface
%    would be fine though, as long as we have declared the instances
%    before the class is loaded.
%
%    So to make legacy classes work with their existing layout, we
%    should not (ever) overwrite \cs{section} but let the class
%    definition call
%    \cs{@startsection} which would then set up suitable instances and
%    only after that call \cs{ParseLaTeXeHeading}.
%
%    However, that would mean a \enquote{new} class like ltx-article
%    would need to add the above definition and declare or edit the
%    corresponding instances, instead of just declaring or adding the
%    instances.
%
%    A perhaps better alternative could be to delay the definition of
%    \cs{section} and friends until after the class got loaded and
%    then take a peak at \cs{section} as defined by the class and if
%    it contains a \cs{@startsection} call, leave it alone and
%    otherwise overwrite it. And if the class hasn't defined
%    \cs{section} (because it is a new class) declare it. Of course
%    that means \cs{section} would then be available with every class
%    even if it was never meant to contain headings.
%
%    But while writing this up, I start to think it is best if a new
%    class defines both the document interface (i.e., the above
%    command) as well as the layout (declare the instances) and the
%    kernel does neither. It has been this way before and it is
%    consistent, so why change.
%
%    The situation with headings defined via \cs{secdef} is worse: we
%    don't have a nice handle as with \cs{@startsection} so there is
%    no real way other than through static analysis to set up such
%    a heading in the new template style. So all that is possible (I
%    think) is that after the class has been loaded, we look if the
%    usual candidates (\cs{part} and \cs{chapter}) have been defined
%    and overwrite them with a standard layout. That would make the
%    class tagging aware but, of course, would likely change the
%    layout.
%
%    The current implementation
%    \begin{itemize}
%    \item provides instance for the heading commands of the standard classes;
%    \item declares the heading commands for the standard classes with
%    the new interfaces through class hooks;
%    \item other classes call the adapted \cs{@startsection}; other headings
%    command like \cs{part} or \cs{chapter} are not handled and must be setup
%    individually.
%    \end{itemize}
%
% \subsubsection{Instances (sample/default definitions)}
%
%
%  \begin{instance}{heading part}
%  An instance suitable for \cls{book} and \cls{report}. An instance suitable
%  for \cls{article} is above in the hook.
%    \begin{macrocode}
\DeclareInstance{heading}{part}{display}
{
  , name          = part
  , level         = -1
  , placement     = page
  , after-penalty-vspace = 0pt
  , prefix        = \partname
  , number-format = \thepart
  , heading-decls = \centering\bfseries\huge
  , title-decls   = \Huge
  , headformat-instance = part
  , mark-cmd      = \partmark {#1}
}
%    \end{macrocode}
%  \end{instance}
%
%  \begin{instance}{heading chapter}
%
%    \begin{macrocode}
\DeclareInstance{heading}{chapter}{display}
{
  , name           = chapter
  , level          = 0
  , placement      = top
  , column-spanning = true
  , after-penalty-vspace = 50pt
  , after-vspace   = 40pt
  , prefix         = \@chapapp
  , number-format  = \thechapter
  , heading-decls  = \raggedright \parindent0pt \bfseries \huge
  , title-decls    = \Huge
  , headformat-instance = chapter
  , mark-cmd       = \chaptermark {#1}
  , contents-extra = \addtocontents{lof}{\addvspace{10pt}}
                     \addtocontents{lot}{\addvspace{10pt}}
}
%    \end{macrocode}
%  \end{instance}
%
%
%  \begin{macro}{\@chapapp}
%    To improve compatibility with classes that use \cs{secdef} but
%    don't provide a definition for \cs{@chapapp} used in the
%    \key{prefix} key above, we define this command if
%    necessary. Otherwise such a class would error if \cs{chapter} is
%    used.
% \changes{0.9h}{2026-07-08}{Define \cs{@chapapp}, if necessary (tagging/1482)}
%    \begin{macrocode}
\AtBeginDocument{
  \cs_if_exist:NF \@chapapp { \cs_new:Npn \@chapapp {Chapter} } }
%    \end{macrocode}
%  \end{macro}
%  \begin{instance}{heading section}
%
%    \begin{macrocode}
\DeclareInstance{heading}{section}{display}
{
  , name          = section
  , level         = 1
  , mark-cmd      = \sectionmark {#1}
  , before-vspace = 3.5ex plus 1ex minus .2ex
  , after-vspace  = 2.3ex plus .2ex
  , heading-decls = \normalfont\Large\bfseries
  , headformat-instance = section
}
%    \end{macrocode}
%  \end{instance}
%
%
%  \begin{instance}{heading subsection}
%
%    \begin{macrocode}
\DeclareInstance{heading}{subsection}{display}
{
  , name          = subsection
  , parent-name   = section
  , level         = 2
  , mark-cmd      = \subsectionmark {#1}
  , before-vspace = 3.25ex plus 1ex minus .2ex
  , after-vspace  = 1.5ex plus .2ex
  , heading-decls = \normalfont\large\bfseries
  , headformat-instance = subsection
}
%    \end{macrocode}
%  \end{instance}
%
%
%  \begin{instance}{heading subsubsection}
%
%    \begin{macrocode}
\DeclareInstance{heading}{subsubsection}{display}
{
  , name          = subsubsection
  , parent-name   = subsection
  , level         = 3
  , before-vspace = 3.25ex plus 1ex minus .2ex
  , after-vspace  = 1.5ex plus .2ex
  , heading-decls = \normalfont\normalsize\bfseries
  , headformat-instance = subsubsection
}
%    \end{macrocode}
%  \end{instance}
%
%  \begin{instance}{heading paragraph}
%
%    \begin{macrocode}
\DeclareInstance{heading}{paragraph}{runin}
{
  , name          = paragraph
  , parent-name   = subsubsection
  , level         = 4
  , before-vspace = 3.25ex \@plus1ex \@minus.2ex
  , after-vspace  = 1em
  , heading-decls = \normalfont\normalsize\bfseries
  , mark-cmd      =  \paragraphmark {#1}
  , headformat-instance = paragraph

}
%    \end{macrocode}
%  \end{instance}
%
%
%
%  \begin{instance}{heading subparagraph}
%
%    \begin{macrocode}
\DeclareInstance{heading}{subparagraph}{runin}
{
  , name          = subparagraph
  , parent-name   = paragraph
  , level         = 5
  , before-vspace = 3.25ex \@plus1ex \@minus .2ex
  , after-vspace  = 1em
  , heading-decls = \normalfont\normalsize\bfseries
  , mark-cmd      =  \subparagraphmark {#1}
  , headformat-instance = subparagraph

}
%    \end{macrocode}
%  \end{instance}
%
%  \begin{instance}{headformat part}
%  \begin{instance}{headformat chapter}
%    The \texttt{headformat} instances for part and chapter use the
%    \texttt{display} template with identical settings by default,
%    so one is made a copy of the other to speed up loading.
%    \begin{macrocode}
\DeclareInstance{headformat}{part}{display}
{
  , heading-indent    = 0pt
  , prefix-number-sep = \WordSpaceAmount{1}
}
%    \end{macrocode}
%    
%    \begin{macrocode}
\DeclareInstanceCopy{headformat}{chapter}{part}
%    \end{macrocode}
%  \end{instance}
%  \end{instance}
%
%
%  \begin{instance}{headformat std}
%  \begin{instance}{headformat section}
%  \begin{instance}{headformat subsection}
%  \begin{instance}{headformat subsubsection}
%    Similarly, by default the instances for section, subsection, and
%    subsubsection are all using the \texttt{hang} template and the
%    same key values as the \texttt{std} instance, so they
%    are all made a copy of that one.
%    \begin{macrocode}
\DeclareInstance{headformat}{std}{hang}
{
  , heading-indent = 0pt
}
%    \end{macrocode}
%    
%    \begin{macrocode}
\DeclareInstanceCopy{headformat}{section}{std}
\DeclareInstanceCopy{headformat}{subsection}{std}
\DeclareInstanceCopy{headformat}{subsubsection}{std}
%    \end{macrocode}
%  \end{instance}
%  \end{instance}
%  \end{instance}
%  \end{instance}
%
%
%  \begin{instance}{headformat paragraph}
%  \begin{instance}{headformat subparagraph}
%    In contrast, paragraph and subparagraph differ even though both
%    use the \texttt{runin} template.
%    \begin{macrocode}
\DeclareInstance{headformat}{paragraph}{runin}
{
  , heading-indent = 0pt
}
%    \end{macrocode}
%
%    \begin{macrocode}
\DeclareInstance{headformat}{subparagraph}{runin}
{
  , heading-indent = \parindent
}
%    \end{macrocode}
%  \end{instance}
%  \end{instance}
%
%
%  \begin{instance}{headformat section-special}
%
%    A special headformat instance for testing. It can be used with
%    \verb+\section[headformat-instance=section-special]{bla}+
%    \begin{macrocode}
\DeclareInstance{headformat}{section-special}{hang}
{
  , heading-indent = 4em
  , title-format   = {#1!}
}
%    \end{macrocode}
%  \end{instance}
%

% \subsubsection{New \cs{@startsection}}
%
%  \begin{macro}{\@startsection}
%    To support legacy classes that implement headings through a call
%    to \cs{@startsection} we redefine this command to generate a
%    \text{heading} instance from the arguments of \cs{@startsection} if
%    it doesn't yet exist and then use this instance to typeset the
%    heading.
%
%    NOTE: To handle legacy definition like
%    \verb+{\normalfont\Large\bfseries\MakeUppercase}+ in the last argument
%    it copies this argument both to
%    \texttt{heading-decls} and to \texttt{title-format}.
%
%    \begin{macrocode}
\DeclareDocumentCommand \@startsection {mmmmmm s ={shorttitle}o m}{
%    \end{macrocode}
%    If there already exists an instance \texttt{\#1-@startsection} then arguments
%    2--6 are ignored and we simply call that instance. Otherwise we
%    go through the process to set it up. This allows classes, packages
%    and authors to create and overwrite definitions with \cs{@startsection}.
%    But after a call to a command using the \cs{@startsection}
%    the instances are created. It is therefore not possible to redefine the command
%    after a first use or to create two commands using the same level, e.g. \cs{section}
%    and \cs{specialsection}. Such setups should use the new interfaces to declare
%    heading commands.
%    \begin{macrocode}
  \IfInstanceExistsF{heading}{#1-@startsection}{
%    \end{macrocode}
%
%    \begin{macrocode}
    \@@_debug_typeout:n{Info:~ setting~ up~ instances~ for~
                       legacy~ \string\@startsection}
%    \end{macrocode}
%    In the \LaTeXe{} logic a negative \#4 means we do not indent the
%    following paragraph \ldots
%
%    It is okay to change any \texttt{em} or \texttt{ex}
%    specifications to real \texttt{pt} values here, because this code
%    is executed in the same place where \cs{@startsection} is
%    normally executed and inside the original definitions such
%    assignments happen as well, before there is any font change
%    happening for \#4 and \#5.
%    \begin{macrocode}
    \@tempskipa #4\relax
    \@afterindenttrue
    \ifdim \@tempskipa <\z@
      \@tempskipa -\@tempskipa
      \@afterindentfalse
    \fi
%    \end{macrocode}
%    \ldots\ and a negative \#5 means we should produce a runin heading.
%    \begin{macrocode}
    \@tempskipb #5\relax
    \ifdim \@tempskipb>\z@
      \use:e {
        \DeclareInstance{heading}{#1-@startsection}{display}{
         , name          = #1
         , level         = #2
         , mark-cmd      = \exp_not:c {#1mark} {##1}
         , before-vspace = \the\@tempskipa
         , after-vspace  = \the\@tempskipb
         , para-indent   = \if@afterindent true \else false\fi
         , heading-decls = \exp_not:n {#6}
%    \end{macrocode}
% we also do the declarations in \texttt{title-format} to handle
% settings which ends, e.g., with \cs{MakeUppercase},
%    \begin{macrocode}
         , headformat-instance = #1-@startsection
      }}
%    \end{macrocode}
%    We can expect that the instance \texttt{\#1-@startsection} is not
%    set up by the user if \texttt{\#1-@startsection} isn't, so no check.
%    \begin{macrocode}
      \DeclareInstance{headformat}{#1-@startsection}{hang}{heading-indent = #3,title-format={#6{##1}}}
    \else
      \@tempskipb=-\@tempskipb
      \use:e {
       \DeclareInstance{heading}{#1-@startsection}{runin}{
         , name          = #1
         , level         = #2
         , mark-cmd      = \exp_not:c {#1mark} {##1}
         , before-vspace = \the\@tempskipa
         , after-vspace  = \the\@tempskipb
         , heading-decls = \exp_not:n{#6}
         , headformat-instance = #1-@startsection
      }}
      \DeclareInstance{headformat}{#1-@startsection}{runin}{heading-indent = #3,title-format={#6{##1}}}
    \fi
  }
  \ParseLaTeXeHeading {#1-@startsection}{#7}{#8}{#9}
}
%    \end{macrocode}
%  \end{macro}
%
% Some classes redefine \cs{@startsection} and then our redefinition is lost. So we
% reinstate it
%    \begin{macrocode}
\NewCommandCopy\kernel@startsection\@startsection
\AddToHook{class/after}[head/@startsection]
  {\RenewCommandCopy\@startsection\kernel@startsection}
%    \end{macrocode}
%
%
%  \subsubsection{New \cs{secdef}}
% The command maps standard \cs{secdef} definition of \cs{part} and \cs{chapter} to
% the new interface. Unknown heading commands warn (or error if tagging is active) and
% then call the old commands.
% \begin{macro}{\secdef}
%    \begin{macrocode}
\RenewDocumentCommand\secdef{mmsO{#5}m}
 {
  \str_case:enF {\cs_to_str:N#1}
   {
    {@part}
     {
       \IfNoValueTF{#4}
        {\ParseLaTeXeHeading{part}{#3} {start-code=\relax} {#5}}
        {
         \@@_process_shorttitle:nN{#4}\l_@@_tmpa_tl
         \ExpandArgs{nne}\ParseLaTeXeHeading{part}{#3}{start-code=\relax,\exp_not:o{\l_@@_tmpa_tl}} {#5}
        }
       \@latex@warning{\noexpand\secdef~detected~in~\noexpand\part~command.\MessageBreak
         \noexpand\part~will~be~redefined~to~use~templates.\MessageBreak
         This~may~change~the~layout!}
       \DeclareDocumentCommand \part {s ={shorttitle}o m}
         { \ParseLaTeXeHeading {part} {##1} {##2} {##3} }
     }
    {@chapter}
     {
       \IfNoValueTF{#4}
        { \ParseLaTeXeHeading{chapter}{#3} {#4} {#5} }
        {
          \@@_process_shorttitle:nN{#4}\l_@@_tmpa_tl
          \ExpandArgs{nno}\ParseLaTeXeHeading{chapter}{#3}{\l_@@_tmpa_tl} {#5}
        }
       \@latex@warning{\noexpand\secdef~detected~in~\noexpand\chapter~command.\MessageBreak
         \noexpand\chapter~will~be~redefined~to~use~templates.\MessageBreak
         This~may~change~the~layout!}
       \DeclareDocumentCommand \chapter {s ={shorttitle}o m}
        { \ParseLaTeXeHeading {chapter} {##1} {##2} {##3} }
     }
   }
   {
    \tag_if_active:TF\@latex@error\@latex@warning
     {\noexpand\secdef~with~unknown~argument~\noexpand#1 found.\MessageBreak
      The~command~can~not~be~adapted~on~the~fly~to~support~tagging.\MessageBreak
      The~heading~command~using~this~\noexpand\secdef~should~be~
                 reimplemented\MessageBreak with~templates}{}
    \IfBooleanTF{#3}{#2{#5}}{#1[#4]{#5}}
   }
 }
%    \end{macrocode}
% A helper command to reprocess the argument as key-val
%    \begin{macrocode}
\NewDocumentCommand\@@_process_shorttitle:nN{={shorttitle}mm}
 { \tl_set:Nn#2{#1} }
%    \end{macrocode}
% \end{macro}
% 
% 
% 
%  \subsubsection{Core \LaTeX{}}
% 
%   We define here as an example the heading commands with the new
%   interfaces for the three standard classes.
%    
%    \begin{macrocode}
\AddToHook{class/article/after}[head/example]
 {
   \DeclareInstance{heading}{part}{display}
     {
      , name          = part
      , level         = -1
      , before-vspace = 4ex
      , after-vspace  = 3ex
      , mark-cmd     = \partmark {#1}
      , prefix        = \partname
      , number-format = \thepart
      , heading-decls = \raggedright\bfseries\Large
      , title-decls   = \huge
      , headformat-instance = part
     }
   \DeclareInstance{headformat}{part}{display}
     {
       , heading-indent    = 0pt
       , number-title-sep  = 0pt
       , prefix-number-sep = \WordSpaceAmount{1}
     }
   \DeclareDocumentCommand \part {s ={shorttitle}o m}
      { \ParseLaTeXeHeading {part} {#1} {#2} {#3} }
   \@@_setup_default_heading:
 }
%    \end{macrocode}
% \changes{0.9b}{2026-01-26}{Correct chapter definition, tagging/1984}
%    \begin{macrocode}
\AddToHook{class/report/after}[head/example]
 {
    \DeclareDocumentCommand \part {s ={shorttitle}o m}
      { \ParseLaTeXeHeading {part} {#1} {#2} {#3} }
    \DeclareDocumentCommand \chapter {s ={shorttitle}o m}
      {
        \ParseLaTeXeHeading {chapter}{#1} {#2} {#3}
      }
    \@@_setup_default_heading:
 }
\AddToHook{class/book/after}[head/example]
 {
    \DeclareDocumentCommand \part {s ={shorttitle}o m}
      { \ParseLaTeXeHeading {part} {#1} {#2} {#3} }
    \DeclareDocumentCommand \chapter {s ={shorttitle}o m}
      {
        \if@mainmatter
         \ParseLaTeXeHeading {chapter}{#1} {#2} {#3}
        \else
         \IfBooleanTF{#1}
          {% starred:
           \ParseLaTeXeHeading {chapter}{\BooleanTrue} {#2} {#3}
          }
          {\IfNoValueTF{#2}
            {\ParseLaTeXeHeading {chapter}{\BooleanTrue} {shorttitle={#3}} {#3}}
            {\ParseLaTeXeHeading {chapter}{\BooleanTrue} {#2} {#3}}
          }
        \fi
      }
    \@@_setup_default_heading:
 }
%    \end{macrocode}
%
%
%
%    \begin{macrocode}
\cs_new_protected:Npn \@@_setup_default_heading:
 {
%    \end{macrocode}
%  \begin{macro}{\section}
%
%    \begin{macrocode}
   \DeclareDocumentCommand \section {s ={shorttitle}o m}
     { \ParseLaTeXeHeading {section} {##1} {##2} {##3} }
%    \end{macrocode}
%  \end{macro}
%
%  \begin{macro}{\subsection}
%
%    \begin{macrocode}
   \DeclareDocumentCommand \subsection {s ={shorttitle}o m}
     { \ParseLaTeXeHeading {subsection} {##1} {##2} {##3} }
%    \end{macrocode}
%  \end{macro}
%
%  \begin{macro}{\subsubsection}
%
%    \begin{macrocode}
   \DeclareDocumentCommand \subsubsection {s ={shorttitle}o m}
     { \ParseLaTeXeHeading {subsubsection} {##1} {##2} {##3}  }
%    \end{macrocode}
%  \end{macro}
%
%  \begin{macro}{\paragraph}
%
%    \begin{macrocode}
   \DeclareDocumentCommand \paragraph {s ={shorttitle}o m}
     { \ParseLaTeXeHeading {paragraph} {##1} {##2} {##3} }
%    \end{macrocode}
%  \end{macro}
%
%  \begin{macro}{\subparagraph}
%
%    \begin{macrocode}
   \DeclareDocumentCommand \subparagraph {s ={shorttitle}o m}
     { \ParseLaTeXeHeading {subparagraph} {##1} {##2} {##3} }
 } %end of command
%    \end{macrocode}
%  \end{macro}

%    \begin{macrocode}
%</package>
%    \end{macrocode}
%
% \section{Issues and problems noticed along the way}
%
% \subsection{Local \cs{DeclareInstance}}
%
%    \cs{DeclareInstance} does its declaration locally. That might be the
%    right decision (or not) but we need to make sure that it in that
%    case all of the declaration is local.
%
%    One potential problem with that is that it might allocate \TeX{}
%    registers.
%
%    The problem showed up in the redefinition of \cs{@startsection},
%    because in the current document some headings are local to an
%    environment, so things get redeclared over and over again.
%
% \subsection{\cs{SetCurrentTemplateKeys}}
%
%    Furthermore, I think I would like to have some
%    \cs{SetCurrentTemplateKeys} where one does not have to specify
%    the type nor the template name, because that is how it is always
%    used (by me).
%
% \subsection{O-expansion of \cs{UseInstance} arguments}
%
%    Whenever a template code calls a sub-instance and that
%    sub-instance takes arguments, then the values for these arguments
%    are typically inside tokenlists or registers so that for
%    efficiency (and sometimes as a total must) one has to o-expand
%    all arguments. While that can be coded somehow, e.g.,
% \begin{verbatim}
%   \use:e {
%     \UseInstance{headformat} { \l_@@_headformat_instance_tl }
%                 { \exp_not:o \UnusedTemplateKeys }
%                 { \exp_not:o { \l_@@_typeset_number_tl } }
%                 { \exp_not:n { #3 } }
%                 { \exp_not:o { \use_i:nn  #9 } }
%                 { \exp_not:o { \use_ii:nn  #9 } }
%   }
% \end{verbatim}
%
%    it would be better to have a version of \cs{UseInstance} that
%    does this automatically. No suggestion for a name.
%
%
%
% \subsection{Switch \cs{openright} is not defined by core}
%
%   I think this should change and it might be enough to just define
%    it in the kernel (I think \cs{newif} no longer complains if it
%    acts on an existing \cs{if...}
%
% \subsection{Indexheading at least for l3doc is wrong now}
%
%  Needs checking.
%
% \end{implementation}
%
%
%
% \Finale
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\endinput
