% \iffalse meta-comment
%
% File: postnotes.dtx
%
% This file is part of the LaTeX package "postnotes".
%
% Copyright (C) 2022-2024  gusbrs
%
% 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
%
% and version 1.3 or later is part of all distributions of LaTeX
% version 2005/12/01 or later.
%
%
% This work is "maintained" (as per LPPL maintenance status) by gusbrs.
%
% This work consists of the files postnotes.dtx,
%                                 postnotes.ins,
%                                 postnotes-doc.tex,
%                                 postnotes-code.tex,
%                   and the files generated from them.
%
% The released version of this package is available from CTAN.
%
% -----------------------------------------------------------------------
%
% The development version of the package can be found at
%
%    https://github.com/gusbrs/postnotes
%
% for those people who are interested.
%
% -----------------------------------------------------------------------
%
% \fi
%
% \iffalse
%<*driver>
\documentclass{l3doc}

% Have \GetFileInfo pick up date and version data and used in the
% documentation.
\usepackage{postnotes}

\begin{document}

\DocInput{postnotes.dtx}

\end{document}
%</driver>
%
% \fi
%
% \DoNotIndex{\\}
%
% \NewDocumentCommand\githubissue{m}{^^A
%   issue~\href{https://github.com/gusbrs/postnotes/issues/#1}{\##1}}
%
% \NewDocumentCommand\githubPR{m}{^^A
%   PR~\href{https://github.com/gusbrs/postnotes/pull/#1}{\##1}}
%
% \NewDocumentCommand\contributor{m}{#1}
% \NewDocumentCommand\username{m}{`\texttt{#1}'}
%
% \NewDocumentCommand\opt{m}{\texttt{#1}}
%
% \pdfstringdefDisableCommands{^^A
%   \def\opt#1{#1}
% }
%
% \AddToHook{env/macro/after}{\medskip{}}
% \AddToHook{env/variable/after}{\medskip{}}
% \AddToHook{env/function/after}{\medskip{}}
%
%
% ^^A Have the Index at 'section' level rather than 'part'.  Otherwise it is
% ^^A just the same definition from 'l3doc.cls'.
% \IndexPrologue{^^A
%   \section*{Index}
%   \markboth{Index}{Index}
%   \addcontentsline{toc}{section}{Index}
%   The italic numbers denote the pages where the corresponding entry is
%   described, numbers underlined point to the definition, all others indicate
%   the places where it is used.^^A
% }
%
%
% \GetFileInfo{postnotes.sty}
%
% \title{^^A
%   The \pkg{postnotes} package^^A
%   \texorpdfstring{\\{}\medskip{}}{ - }^^A
%   Code documentation^^A
%   \texorpdfstring{\medskip{}}{}^^A
% }
%
% \author{^^A
%   \texorpdfstring{\texttt{gusbrs}\\[0.8em]
%   \url{https://github.com/gusbrs/postnotes}\\
%   \url{https://www.ctan.org/pkg/postnotes}}{gusbrs}}
%
% \date{Version \fileversion\ -- \filedate}
%
% \maketitle
%
%
% \tableofcontents
%
%
% \clearpage{}
%
% \section{Initial setup}
% Start the \pkg{DocStrip} guards.
%    \begin{macrocode}
%<*package>
%    \end{macrocode}
%
% Identify the internal prefix (\LaTeX3 \pkg{DocStrip} convention).
%    \begin{macrocode}
%<@@=postnotes>
%    \end{macrocode}
%
%
% The new syntax for file/package hooks, which the package assumes, requires
% kernel 2021-11-15 (\texttt{ltnews34}, \texttt{ltfilehook}).  Furthermore,
% the kernel of 2022-06-01 introduced a couple of very nice features which
% simplifies the relation with \pkg{hyperref} (\texttt{ltnews35},
% \texttt{hyperref-linktarget}): the provision of \cs{MakeLinkTarget} and the
% definition by the kernel of the starred version of \cs{ref}, which we can
% use regardless of \pkg{hyperref} being loaded.  Also, since we followed the
% move to \texttt{e}-type expansion, to play safe we require the 2023-11-01
% kernel or newer.  Finally, the tagging sockets and block code required for
% tagging support need the 2024-06-01 kernel.
%
%    \begin{macrocode}
\def\postnotes@required@kernel{2024-06-01}
\NeedsTeXFormat{LaTeX2e}[\postnotes@required@kernel]
\providecommand\IfFormatAtLeastTF{\@ifl@t@r\fmtversion}
\IfFormatAtLeastTF{\postnotes@required@kernel}
  {}
  {%
    \PackageError{postnotes}{LaTeX kernel too old}
      {%
        'postnotes' requires a LaTeX kernel \postnotes@required@kernel\space or newer.%
      }%
  }%
%    \end{macrocode}
%
%
%    \begin{macrocode}
\ProvidesExplPackage {postnotes} {2024-11-04} {0.4.0}
  {Endnotes for LaTeX}
%    \end{macrocode}
%
%
% \begin{macro}
%   {
%      \l_@@_tmpa_tl ,
%      \l_@@_tmpb_tl ,
%      \l_@@_tmpa_seq ,
%      \l_@@_tmpb_seq ,
%      \l_@@_tmpa_box ,
%   }
%   Temporary scratch variables.
%    \begin{macrocode}
\tl_new:N \l_@@_tmpa_tl
\tl_new:N \l_@@_tmpb_tl
\seq_new:N \l_@@_tmpa_seq
\seq_new:N \l_@@_tmpb_seq
\box_new:N \l_@@_tmpa_box
%    \end{macrocode}
% \end{macro}
%
%
% \section{Data}
%
%
% \begin{macro}[EXP]{\@@_data_name:n}
%   Returns the name of the property list variable which stores the data of
%   the \cs{postnote} with \meta{note id} number.
%     \begin{syntax}
%       \cs{@@_data_name:n} \Arg{note id}
%     \end{syntax}
%    \begin{macrocode}
\cs_new:Npn \@@_data_name:n #1
  { g_@@_ #1 _data_prop }
\cs_generate_variant:Nn \@@_data_name:n { e }
%    \end{macrocode}
% \end{macro}
%
%
% \pkg{postnotes} provides a number of hooks from the new hook system to grant
% some points of access in key places of the package.  Note that hooks created
% with \cs{NewHook} are meant to be public interfaces (see
% \url{https://chat.stackexchange.com/transcript/message/62955941#62955941},
% and following discussion).
%
%
% \begin{macro}{\@@_store:nn}
%   Stores the metadata and \meta{note content} of \cs{postnote} with ID
%   \meta{note id}, from where it is called.  The
%   \texttt{postnotes/note/store} hook is intended to add further data to the
%   note, when required to support packages with specific needs.
%     \begin{syntax}
%       \cs{@@_store:nn} \Arg{note id} \Arg{note content}
%     \end{syntax}
%    \begin{macrocode}
\NewHook { postnotes/note/store }
\cs_new_protected:Npn \@@_store:nn #1#2
  {
    \prop_new:c { \@@_data_name:e {#1} }
    \prop_gput:cnn { \@@_data_name:e {#1} } { type } { note }
    \prop_gput:cne { \@@_data_name:e {#1} } { mark }
      { \l_@@_mark_tl }
    \prop_gput:cne { \@@_data_name:e {#1} } { counter }
      { \int_use:N \c@postnote }
    \prop_gput:cne { \@@_data_name:e {#1} } { sortnum }
      {
        \bool_if:NTF \l_@@_manual_sortnum_bool
          { \fp_use:N \l_@@_sort_num_fp }
          { \int_use:N \c@postnote }
      }
    \cs_if_exist:cT { chapter }
      {
        \prop_gput:cne { \@@_data_name:e {#1} }
          { thechapter } { \thechapter }
      }
    \prop_gput:cne { \@@_data_name:e {#1} } { thesection }
      { \thesection }
    \prop_gput:cne { \@@_data_name:e {#1} } { pnsectname }
      { \g_@@_section_name_tl }
    \prop_gput:cne { \@@_data_name:e {#1} } { pnsectid }
      { \int_use:N \g_@@_sectid_int }
    \prop_gput:cne { \@@_data_name:e {#1} } { multibool }
      { \bool_to_str:N \l_@@_maybe_multi_bool }
    \prop_gput:cnn { \@@_data_name:e {#1} } { content } {#2}
    \UseHook { postnotes/note/store }
  }
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\@@_store_section:nn}
%   Stores the metadata and \meta{note content} of \cs{postnotesection} with
%   ID \meta{note id}, from where it is called.
%     \begin{syntax}
%       \cs{@@_store_section:nn} \Arg{note id} \Arg{note content}
%     \end{syntax}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_store_section:nn #1#2
  {
    \prop_new:c { \@@_data_name:e {#1} }
    \prop_gput:cnn { \@@_data_name:e {#1} } { type } { section }
    \cs_if_exist:cT { chapter }
      {
        \prop_gput:cne { \@@_data_name:e {#1} }
          { thechapter } { \thechapter }
      }
    \prop_gput:cne { \@@_data_name:e {#1} } { thesection }
      { \thesection }
    \prop_gput:cnn { \@@_data_name:e {#1} } { content } {#2}
  }
\cs_generate_variant:Nn \@@_store_section:nn { ne }
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}
%   {
%     \@@_prop_get:nnN ,
%     \@@_prop_item:nn ,
%     \@@_prop_gclear:n ,
%   }
%   Convenience functions to retrieve and clear data from a note based on the
%   ID number.
%     \begin{syntax}
%       \cs{@@_prop_get:nnN} \Arg{note id} \Arg{property} \Arg{tl var to set}
%       \cs{@@_prop_item:nn} \Arg{note id} \Arg{property}
%       \cs{@@_prop_gclear:n} \Arg{note id}
%     \end{syntax}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_prop_get:nnN #1#2#3
  {
    \prop_get:cnNF { \@@_data_name:e {#1} } {#2} #3
      { \tl_clear:N #3 }
  }
\cs_new:Npn \@@_prop_item:nn #1#2
  { \prop_item:cn { \@@_data_name:e {#1} } {#2} }
\cs_new_protected:Npn \@@_prop_gclear:n #1
  { \prop_gclear:c { \@@_data_name:e {#1} } }
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}[int]
%   {
%     \post@note ,
%     \@@_store_labelseq:nn ,
%     \@@_step_counteraux:nnn ,
%   }
%   \cs{post@note} is the \cs{newlabel} equivalent for \pkg{postnotes}.
%   Based on the kernel's \cs{@newl@bel} so that we get \LaTeX{} checks for
%   multiple and changed references for free (procedure learnt from
%   \pkg{zref}).  \cs{post@note}, when the \file{.aux} file is read, defines
%   macros named \texttt{\textbackslash{}postnote@r@\meta{label
%   type}@\meta{id}}, according to the prefix set by \cs{c_@@_ref_prefix_tl}.
%   \cs{@@_store_labelseq:nn} is an auxiliary function to store the sequence
%   of the labels in the \file{.aux} file, used to check for possible sorting
%   problems due to floats. \cs{@@_step_counteraux:nnn} handles counter
%   stepping and storing for the \opt{counteraux} option.
%     \begin{syntax}
%       \cs{post@note} \Arg{label type} \Arg{id} \Arg{label content (page)}
%       ~~\Arg{counteraux step}
%       \cs{@@_store_labelseq:nn} \Arg{label type} \Arg{id}
%       \cs{@@_step_counteraux:nnn} \Arg{label type} \Arg{id}
%       ~~\Arg{counteraux step}
%     \end{syntax}
%    \begin{macrocode}
\tl_const:Nn \c_@@_ref_prefix_tl { postnote@r }
\seq_new:N \g_@@_labelseq_seq
\int_new:N \g_@@_postnote_counteraux_int
\prop_new:N \g_@@_counteraux_prop
\bool_new:N \g_@@_firstrun_bool
\bool_gset_true:N \g_@@_firstrun_bool
\cs_new_protected:Npn \@@_store_labelseq:nn #1#2
  {
    \bool_lazy_any:nT
      {
        { \str_if_eq_p:nn {#1} { mark } }
        { \str_if_eq_p:nn {#1} { section } }
        { \str_if_eq_p:nn {#1} { preprint } }
      }
      { \seq_gput_right:Nn \g_@@_labelseq_seq { {#1} {#2} } }
  }
\cs_new_protected:Npn \@@_step_counteraux:nnn #1#2#3
  {
    \bool_lazy_and:nnT
      { \g_@@_counteraux_bool }
      { \str_if_eq_p:nn {#1} { mark } }
      {
        \int_gadd:Nn \g_@@_postnote_counteraux_int { #3 }
        \prop_gput:Nne \g_@@_counteraux_prop { #2 }
          { \int_use:N \g_@@_postnote_counteraux_int }
      }
  }
\cs_new_protected:Npe \post@note #1#2#3#4
  {
    \exp_not:N \bool_gset_false:N \exp_not:N \g_@@_firstrun_bool
    \exp_not:N \@@_store_labelseq:nn { #1 } { #2 }
    \exp_not:N \@@_step_counteraux:nnn { #1 } { #2 } { #4 }
    \exp_not:N \@newl@bel { \c_@@_ref_prefix_tl } { #1 @ #2 } { #3 }
  }
%    \end{macrocode}
% \end{macro}
%
% And ensure \cs{post@note}, \cs{postnote@setcounteraux}, and
% \cs{postnote@addtocounteraux} are defined in the \file{.aux} file.  The
% hooks are the same used by \pkg{hyperref} for similar purpose.
%
%    \begin{macrocode}
\AddToHook { begindocument }
  {
    \legacy_if:nT { @filesw }
      {
        \iow_now:Ne \@mainaux
          {
            \token_to_str:N \providecommand
            \token_to_str:N \post@note [4] { }
          }
        \iow_now:Ne \@mainaux
          {
            \token_to_str:N \providecommand
            \token_to_str:N \postnote@setcounteraux [1] { }
          }
        \iow_now:Ne \@mainaux
          {
            \token_to_str:N \providecommand
            \token_to_str:N \postnote@addtocounteraux [1] { }
          }
      }
  }
\AddToHook { include/before }
  {
    \legacy_if:nT { @filesw }
      {
        \iow_now:Ne \@mainaux
          {
            \token_to_str:N \providecommand
            \token_to_str:N \post@note [4] { }
          }
        \iow_now:Ne \@mainaux
          {
            \token_to_str:N \providecommand
            \token_to_str:N \postnote@setcounteraux [1] { }
          }
        \iow_now:Ne \@mainaux
          {
            \token_to_str:N \providecommand
            \token_to_str:N \postnote@addtocounteraux [1] { }
          }
      }
  }
%    \end{macrocode}
%
%
% \begin{macro}
%   {
%     \@@_set_label:nnnn ,
%     \@@_set_mark_page_label:nn ,
%     \@@_set_section_page_label:n ,
%     \@@_set_text_page_label:n ,
%     \@@_set_print_page_label:n ,
%     \@@_set_pre_print_label:n ,
%   }
%   Label setting functions for each pertinent context.  They must use
%   \cs{iow_shipout_e:Nn}, since the main information we are interested in is
%   the \texttt{page}.
%     \begin{syntax}
%       \cs{@@_set_label:nnnn} \Arg{label type} \Arg{note id} \Arg{value}
%       ~~\Arg{counteraux step}
%       \cs{@@_set_mark_page_label:nn} \Arg{note id} \Arg{counteraux step}
%       \cs{@@_set_section_page_label:n} \Arg{note id}
%       \cs{@@_set_text_page_label:n} \Arg{note id}
%       \cs{@@_set_print_page_label:n} \Arg{note id}
%       \cs{@@_set_pre_print_label:n} \Arg{note id}
%     \end{syntax}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_set_label:nnnn #1#2#3#4
  {
    \legacy_if:nT { @filesw }
      {
        \iow_shipout_e:Nn \@auxout
          { \token_to_str:N \post@note { #1 } { #2 } { #3 } { #4 } }
      }
  }
\cs_new_protected:Npn \@@_set_mark_page_label:nn #1#2
  { \@@_set_label:nnnn { mark } { #1 } { \thepage } { #2 } }
\cs_generate_variant:Nn \@@_set_mark_page_label:nn { ee }
\cs_new_protected:Npn \@@_set_section_page_label:n #1
  { \@@_set_label:nnnn { section } { #1 } { \thepage } { } }
\cs_generate_variant:Nn \@@_set_section_page_label:n { e }
\cs_new_protected:Npn \@@_set_text_page_label:n #1
  { \@@_set_label:nnnn { text } { #1 } { \int_use:N \c@page } { } }
\cs_generate_variant:Nn \@@_set_text_page_label:n { e }
\cs_new_protected:Npn \@@_set_print_page_label:n #1
  { \@@_set_label:nnnn { print } { #1 } { \int_use:N \c@page } { } }
\cs_generate_variant:Nn \@@_set_print_page_label:n { e }
\cs_new_protected:Npn \@@_set_pre_print_label:n #1
  { \@@_set_label:nnnn { preprint } { #1 } { } { } }
\cs_generate_variant:Nn \@@_set_pre_print_label:n { e }
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}
%   {
%     \@@_get_pageref:Nn ,
%     \@@_extract_pageref:n ,
%   }
%   Reference data extraction functions.
%     \begin{syntax}
%       \cs{@@_get_pageref:Nn} \Arg{tl var to set} \Arg{label name}
%       \cs{@@_extract_pageref:n} \Arg{label name}
%     \end{syntax}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_get_pageref:Nn #1#2
  {
    \cs_if_exist:cTF { \c_@@_ref_prefix_tl @ #2 }
      { \tl_set:Nv #1 { \c_@@_ref_prefix_tl @ #2 } }
      { \tl_clear:N #1 }
  }
\cs_generate_variant:Nn \@@_get_pageref:Nn { Ne }
\cs_new:Npn \@@_extract_pageref:n #1
  {
    \cs_if_exist:cTF { \c_@@_ref_prefix_tl @ #1 }
      { \exp_not:v { \c_@@_ref_prefix_tl @ #1 } }
      { \c_empty_tl }
  }
\cs_generate_variant:Nn \@@_extract_pageref:n { e }
%    \end{macrocode}
% \end{macro}
%
%
% \section{Options}
%
% \subsection*{\opt{heading} option}
%
%    \begin{macrocode}
\keys_define:nn { postnotes/setup }
  {
    heading .cs_set_protected:Np = \pnheading ,
    heading .value_required:n = true ,
  }
%    \end{macrocode}
%
% \begin{macro}[int]{\pnheading}
%   Provide default value for \cs{pnheading}.
%    \begin{macrocode}
\cs_if_exist:cTF { chapter }
  {
    \cs_new_protected:Npn \pnheading
      {
        \chapter*{\pntitle}
        \@mkboth{\pnheaderdefault}{\pnheaderdefault}
      }
  }
  {
    \cs_new_protected:Npn \pnheading
      {
        \section*{\pntitle}
        \@mkboth{\pnheaderdefault}{\pnheaderdefault}
      }
  }
%    \end{macrocode}
% \end{macro}
%
%
% \subsection*{\opt{format} option}
%
%    \begin{macrocode}
\tl_new:N \l_@@_print_format_tl
\keys_define:nn { postnotes/setup }
  {
    format .tl_set:N = \l_@@_print_format_tl ,
    format .initial:n = { \small } ,
    format .value_required:n = true ,
  }
%    \end{macrocode}
%
%
% \subsection*{\opt{listenv} option}
%
%    \begin{macrocode}
\tl_new:N \l_@@_print_env_tl
\bool_new:N \l_@@_print_as_list_bool
\keys_define:nn { postnotes/setup }
  {
    listenv .code:n =
      {
        \tl_if_eq:nnTF {#1} { none }
          {
            \bool_set_false:N \l_@@_print_as_list_bool
            \tl_set:Nn \l_@@_post_printnote_tl { \par }
%    \end{macrocode}
% A sensible default just in case.  It should not get to be used though.
%    \begin{macrocode}
            \tl_set:Nn \l_@@_print_env_tl { itemize }
          }
          {
            \bool_set_true:N \l_@@_print_as_list_bool
            \tl_set:Nn \l_@@_print_env_tl {#1}
          }
      } ,
    listenv .initial:n = { postnoteslist } ,
    listenv .value_required:n = true ,
  }
%    \end{macrocode}
%
%
% A couple of built-in list environments provided for convenience, and
% \texttt{postnoteslist} as default.  The horizontal setup of the label in
% these lists is based on the \texttt{description} environment of the standard
% classes (see the \emph{The \LaTeX{} Companion}).
%
%    \begin{macrocode}
\NewDocumentEnvironment { postnoteslist } { }
  {
    \list { }
      {
        \setlength { \leftmargin }    { 0pt }
        \setlength { \labelwidth }    { 0pt }
        \setlength { \itemindent }    { .5\parindent }
        \cs_set_eq:NN \makelabel \@@_list_makelabel:n
        \setlength { \rightmargin }   { 0pt }
        \setlength { \listparindent } { \parindent }
        \setlength { \parsep }    { \parskip }
        \setlength { \itemsep }   { 0pt }
        \setlength { \topsep }    { .5\topsep }
        \setlength { \partopsep } { .5\partopsep }
      }
  }
  { \endlist }
\NewDocumentEnvironment { postnoteslisthang } { }
  {
    \list { }
      {
        \setlength { \leftmargin }    { 1em }
        \setlength { \labelwidth }    { -\leftmargin }
        \setlength { \itemindent }    { -2\leftmargin }
        \cs_set_eq:NN \makelabel \@@_list_makelabel:n
        \setlength { \rightmargin }   { 0pt }
        \setlength { \listparindent } { \parindent }
        \setlength { \parsep }    { \parskip }
        \setlength { \itemsep }   { 0pt }
        \setlength { \topsep }    { .5\topsep }
        \setlength { \partopsep } { .5\partopsep }
      }
  }
  { \endlist }
\cs_new:Npn \@@_list_makelabel:n #1
  { \hspace { \labelsep } \normalfont ~ #1 }
%    \end{macrocode}
%
%
% \subsection*{\opt{makemark} and \opt{maketextmark} options}
%
% The arguments are: \texttt{\#1} is the mark, \texttt{\#2} and \texttt{\#3}
% are, respectively, the start and the end of the backlink.
%
%    \begin{macrocode}
\keys_define:nn { postnotes/setup }
  {
    makemark .cs_set:Np = \@@_make_mark:nnn #1#2#3 ,
    makemark .value_required:n = true ,
%    \end{macrocode}
% From the default kernel definition of \cs{@makefnmark}.
%    \begin{macrocode}
    makemark .initial:n =
      { #2 \hbox { \@textsuperscript { \normalfont #1 } } #3 } ,
    maketextmark .cs_set:Np = \@@_make_text_mark:nnn #1#2#3  ,
    maketextmark .value_required:n = true ,
    maketextmark .initial:n = { #2 #1 . #3 } ,
  }
\cs_generate_variant:Nn \@@_make_mark:nnn { Vnn }
%    \end{macrocode}
%
%
% \subsection*{\opt{pretextmark}, \opt{posttextmark}, \opt{postprintnote} options}
%
%    \begin{macrocode}
\tl_new:N \l_@@_pre_textmark_tl
\tl_new:N \l_@@_post_textmark_tl
\tl_new:N \l_@@_post_printnote_tl
\keys_define:nn { postnotes/setup }
  {
    pretextmark .tl_set:N = \l_@@_pre_textmark_tl ,
    pretextmark .value_required:n = true ,
    posttextmark .tl_set:N = \l_@@_post_textmark_tl ,
    posttextmark .value_required:n = true ,
    postprintnote .tl_set:N = \l_@@_post_printnote_tl ,
    postprintnote .value_required:n = true ,
  }
%    \end{macrocode}
%
%
% \subsection*{\opt{style} option}
%
%    \begin{macrocode}
\keys_define:nn { postnotes/setup }
  {
    style .choice: ,
    style / endnotes .meta:n =
      {
        listenv = none ,
        format =
          {
            \footnotesize
            \setlength { \rightskip } { 0pt   }
            \setlength { \leftskip  } { 0pt   }
            \setlength { \parindent } { 1.8em }
          } ,
%    \end{macrocode}
% \pkg{endnotes} uses a zero width box to get the desired alignment to the
% right, but that does not play well with the backlinks, so we have a little
% more work to do to get this right.
%    \begin{macrocode}
        maketextmark =
          {
            \hbox_set:Nn \l_@@_tmpa_box
              { \@textsuperscript { \normalfont ##1 } }
            \skip_horizontal:n { - \box_wd:N \l_@@_tmpa_box }
            ##2 \box_use:N \l_@@_tmpa_box ##3
          } ,
      } ,
    style / pagenote .meta:n =
      {
        listenv = none ,
        format = { } ,
        pretextmark = { \noindent } ,
        maketextmark = { { \normalfont ##2 ##1 . ##3 } } ,
        posttextmark = { ~ } ,
      } ,
  }
%    \end{macrocode}
%
%
% \subsection*{\opt{hyperref} and \opt{backlink} options}
%
%    \begin{macrocode}
\bool_new:N \l_@@_hyperlink_bool
\bool_new:N \l_@@_hyperref_warn_bool
\bool_new:N \l_@@_backlink_bool
\keys_define:nn { postnotes/setup }
  {
    hyperref .choice: ,
    hyperref / auto .code:n =
      {
        \bool_set_true:N \l_@@_hyperlink_bool
        \bool_set_false:N \l_@@_hyperref_warn_bool
      } ,
    hyperref / true .code:n =
      {
        \bool_set_true:N \l_@@_hyperlink_bool
        \bool_set_true:N \l_@@_hyperref_warn_bool
      } ,
    hyperref / false .code:n =
      {
        \bool_set_false:N \l_@@_hyperlink_bool
        \bool_set_false:N \l_@@_hyperref_warn_bool
      } ,
    hyperref .initial:n = auto ,
    hyperref .default:n = true ,
    backlink .bool_set:N = \l_@@_backlink_bool ,
    backlink .initial:n = true ,
    backlink .default:n = true ,
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\AddToHook { begindocument }
  {
    \IfPackageLoadedTF { hyperref }
      { }
      {
        \bool_if:NT \l_@@_hyperref_warn_bool
          { \msg_warning:nn { postnotes } { missing-hyperref } }
        \bool_set_false:N \l_@@_hyperlink_bool
      }
    \keys_define:nn { postnotes/setup }
      {
        hyperref .code:n =
          {
            \msg_warning:nnn { postnotes }
              { option-preamble-only } { hyperref }
          } ,
        backlink .code:n =
          {
            \msg_warning:nnn { postnotes }
              { option-preamble-only } { backlink }
          } ,
      }
  }
\msg_new:nnn { postnotes } { option-preamble-only }
  { Option~'#1'~only~available~in~the~preamble~\msg_line_context:. }
\msg_new:nnn { postnotes } { missing-hyperref }
  { Missing~'hyperref'~package.~Setting~'hyperref=false'. }
%    \end{macrocode}
%
%
% \subsection*{\opt{multiple}, \opt{multisep} options}
%
% As far as I can tell, the \opt{multiple} option has its origins in the
% \pkg{footmisc} package, which offers this feature for footnotes.  About this
% option, \file{footmisc.dtx} observes:
%
% \begin{quote}
%   This (revised) code derives from a suggestion by Alexander Rozhenko (the
%   author of the \pkg{manyfoot} package): the intention is that
%   \pkg{footmisc} and \pkg{manyfoot} should be able to `interwork', in the
%   sense that each would recognize the other's footnote marks and behave
%   appropriately.  The trick is that both \cs{footnote} and \cs{footnotemark}
%   insert a marker (a cancelling pair of kerns of \cs{multiplefootnotemarker}
%   (of opposite signs), which is detected in following \cs{footnote} or
%   \cs{footnotemark} commands.
% \end{quote}
%
% About the same option, \file{manyfoot.dtx} notes:
%
% \begin{quote}
%   To support \opt{multiple} option from \pkg{footmisc} we add the
%   \cs{FN@mf@prepare} command from \pkg{footmisc} (suggested by Frank
%   Mittelbach).
% \end{quote}
%
% Whatever the exact origin of this feature, the fact is that it has spread
% throughout the ecosystem, using not only the same basic mechanism but,
% typically, using \emph{the same variables}: \cs{multiplefootnotemarker} and
% \cs{multfootsep}.  With the intention, naturally, that different classes and
% packages can ``interwork'' with regard to this feature.  And this became a
% sort of ``shared feature'' in the ecosystem (the list includes
% \pkg{footmisc}, \texttt{KOMA-Script}, \pkg{eledmac}, \pkg{reledmac},
% \cls{tufte}, \cls{memoir}, \pkg{parnotes}, \pkg{sidenotes}, and now also
% \pkg{postnotes}, see discussion at
% \url{https://chat.stackexchange.com/transcript/message/66421777#66421777}).
% What is crucial for this interplay, however, is not quite the variables
% themselves, but \emph{the value of the canceling pair of kerns}, stored in
% \cs{multiplefootnotemarker}.  The fact that the same variables are used by
% most of the classes and packages which provide the feature speaks for
% convenience, in that a change in one of them reflects in all participating
% in the ``pool''.
%
% Convenient as it is, this shared use of the same variables can only work as
% long as the community agrees in what these variables contain to some degree.
% As far as \cs{multiplefootnotemarker} goes, I see no divergence, and
% everybody uses the value of \texttt{3sp} for the canceling kerns from
% \cs{FN@mf@prepare}.  \file{latex-lab-footnotes.dtx} even documents this
% value for this purpose in its list of ``use of kerns to mark h-mode
% positions'' (see
% \url{https://chat.stackexchange.com/transcript/message/66421893#66421893}).
% Things are not as smooth with regard to \cs{multfootsep} though.
% \pkg{footmisc} stores a plain comma in \cs{multfootsep} and applies
% formatting around it in \cs{FN@mf@check} (hard-coded as
% \cs{textsuperscript}).  \texttt{KOMA-Script} also stores plain content in
% \cs{multfootsep} and applies the formatting in the check function.
% \cls{memoir}, however, stores the formatting directly \cs{multfootsep} and
% applies no formatting later.  Also, \file{latex-lab-footmisc.ltx}, in adding
% PDF tagging support for \pkg{footmisc} stores the tagging code directly in
% \cs{multfootsep}.  I don't know if there are others, but these cases are
% already relevant enough to spoil things.  The problem is not that they
% disagree on the value of \cs{multfootsep}, but on the function(s) this macro
% is supposed to perform.  That given, any other parties trying to partake in
% this feature have to handle things differently depending on the value of
% \cs{multfootsep}.  All in all, \pkg{postnotes} takes the cautious stance of
% using internal variables, instead of the shared ones, to implement the
% \opt{multiple} option.  The only thing that really needs to be common is the
% value of the canceling kerns of \texttt{3sp} in \cs{@@_multiple_prepare:}.
%
%    \begin{macrocode}
\tl_new:N \l_@@_multisep_tl
\tl_const:Nn \c_postnotes_multi_notemarker_tl { 3sp }
\bool_new:N \l_@@_multiple_bool
\tl_new:N \l_@@_saved_spacefactor_multi_tl
\keys_define:nn { postnotes/setup }
  {
    multiple .bool_set:N = \l_@@_multiple_bool ,
    multiple .default:n = true ,
    multiple .initial:n = false ,
    multisep .tl_set:N = \l_@@_multisep_tl ,
    multisep .value_required:n = true ,
    multisep .initial:n = {,} ,
  }
%    \end{macrocode}
%
% I'm using the definitions in \pkg{latex-lab-footmisc.ltx} as base, see
% \texttt{texdoc latex-lab-footnotes}.  For the formatting of the separator,
% though, I take inspiration from \texttt{KOMA-Script} and use
% \cs{@@_make_mark:nnn}, instead of hard-coding \cs{textsuperscript}.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_multiple_prepare:
  {
    \bool_if:NT \l_@@_multiple_bool
      {
        \kern -\c_postnotes_multi_notemarker_tl
        \kern  \c_postnotes_multi_notemarker_tl
        \scan_stop:
      }
  }
%    \end{macrocode}
% Note that \cs{@@_multiple_check:} has to be called before any whatsits
% (labels, anchors, etc.) are placed, since they destroy \cs{lastkern} (see
% \url{https://chat.stackexchange.com/transcript/message/66554870#66554870},
% thanks \contributor{Ulrike Fischer}).
%    \begin{macrocode}
\cs_new_protected:Npn \@@_multiple_check:
  {
    \bool_if:NT \l_@@_multiple_bool
      {
        \dim_compare:nNnT
          { \c_postnotes_multi_notemarker_tl } = { \lastkern }
          {
            \tl_set:Ne \l_@@_saved_spacefactor_multi_tl
              { \int_use:N \spacefactor }
            \unkern
            \unkern
            \tag_socket_use:n { postnotes/multisep/begin }
            \@@_make_mark:Vnn \l_@@_multisep_tl { } { }
            \tag_socket_use:n { postnotes/multisep/end }
            \spacefactor \l_@@_saved_spacefactor_multi_tl
            \scan_stop:
          }
      }
  }
%    \end{macrocode}
%
%
% \subsection*{\opt{sort} option}
%
%    \begin{macrocode}
\bool_new:N \l_@@_sort_bool
\keys_define:nn { postnotes/setup }
  {
    sort .bool_set:N = \l_@@_sort_bool ,
    sort .initial:n = true ,
    sort .default:n = true ,
  }
%    \end{macrocode}
%
%
% \subsection*{\opt{checkduplicates} and \opt{checkfloats} options}
%
%    \begin{macrocode}
\bool_new:N \l_@@_check_dupli_bool
\bool_new:N \l_@@_check_floats_bool
\keys_define:nn { postnotes/setup }
  {
    checkduplicates .bool_set:N = \l_@@_check_dupli_bool ,
    checkduplicates .default:n = true ,
    checkduplicates .initial:n = true ,
    checkfloats .bool_set:N = \l_@@_check_floats_bool ,
    checkfloats .default:n = true ,
    checkfloats .initial:n = false ,
  }
%    \end{macrocode}
%
%
% \subsection*{\opt{maybemulti} option}
%
%    \begin{macrocode}
\bool_new:N \l_@@_maybe_multi_bool
\keys_define:nn { postnotes/setup }
  {
    maybemulti .bool_set:N = \l_@@_maybe_multi_bool ,
    maybemulti .default:n = true ,
    maybemulti .initial:n = false ,
  }
%    \end{macrocode}
%
%
% \subsection*{\opt{counteraux} option}
%
%    \begin{macrocode}
\bool_new:N \g_@@_counteraux_bool
\keys_define:nn { postnotes/setup }
  {
    counteraux .bool_gset:N = \g_@@_counteraux_bool ,
    counteraux .default:n = true ,
    counteraux .initial:n = false ,
  }
%    \end{macrocode}
%
%
%    \begin{macrocode}
\AddToHook { begindocument/before }
  {
    \bool_if:NT \g_@@_counteraux_bool
      { \postnotesetup { sort=false } }
    \keys_define:nn { postnotes/setup }
      {
        counteraux .code:n =
          {
            \msg_warning:nnn { postnotes }
              { option-preamble-only } { counteraux }
          } ,
      }
  }
%    \end{macrocode}
%
%
% \begin{macro}[int]
%   {
%     \pnsetcounteraux ,
%     \pnaddtocounteraux ,
%     \postnote@setcounteraux ,
%     \postnote@addtocounteraux ,
%   }
%   \begin{syntax}
%     \cs{pnsetcounteraux}\marg{int}
%     \cs{pnaddtocounteraux}\marg{int}
%     \cs{postnote@setcounteraux}\marg{int}
%     \cs{postnote@addtocounteraux}\marg{int}
%   \end{syntax}
%    \begin{macrocode}
\cs_new_protected:Npn \postnote@setcounteraux #1
  { \int_gset:Nn \g_@@_postnote_counteraux_int { #1 } }
\cs_new_protected:Npn \postnote@addtocounteraux #1
  { \int_gadd:Nn \g_@@_postnote_counteraux_int { #1 } }
\NewDocumentCommand \pnsetcounteraux { m }
  {
    \@bsphack
    \legacy_if:nT { @filesw }
      {
        \iow_shipout_e:Nn \@auxout
          { \token_to_str:N \postnote@setcounteraux { #1 } }
      }
    \@esphack
  }
\NewDocumentCommand \pnaddtocounteraux { m }
  {
    \@bsphack
    \legacy_if:nT { @filesw }
      {
        \iow_shipout_e:Nn \@auxout
          { \token_to_str:N \postnote@addtocounteraux { #1 } }
      }
    \@esphack
  }
%    \end{macrocode}
% \end{macro}
%
%
%
% \subsection*{\cs{postnotesetup}}
%
%
% \begin{macro}[int]{\postnotesetup}
%   Provide \cs{postnotesetup}.
%   \begin{syntax}
%     \cs{postnotesetup}\marg{options}
%   \end{syntax}
%    \begin{macrocode}
\NewDocumentCommand \postnotesetup { m }
  { \keys_set:nn { postnotes/setup } {#1} }
%    \end{macrocode}
% \end{macro}
%
%
% \section{\cs{postnote}}
%
% Different from the traditional \cs{footnotemark} / \cs{footnotetext} system,
% in the context of end notes, the functionality which corresponds to
% \cs{footnotetext} is simply to store the data to be typeset later.  Hence,
% some of the problems that afflict footnotes do not apply to end notes.
% Namely, and as far as I can tell, they can be used in ``inner horizontal
% mode'' (\cs{mbox} etc.), and in math mode, and if the ``text'' will be
% typeset in the same page as the ``mark'' is of little concern.
%
% However, the separation between ``mark'' and ``text'' is still useful in
% other contexts: floats and contexts where multiple typesetting passes are
% performed.  \contributor{David Carlisle} and \contributor{Ulrike Fischer}
% shared some thoughts on the matter at the TeX.SX chat:
% \url{https://chat.stackexchange.com/transcript/message/60754383#60754383}.
%
% The interesting questions here are: if they are replaceable in their roles
% in these contexts and how much would we lose by providing them.  In
% analyzing this, we have to distinguish two situations: when
% \cs{footnotemark} is called with no argument (and thus steps the counter),
% and when it is called with the optional argument (and thus refrains from
% stepping the counter).
%
% For floats, the problem they pose is that they may disturb the
% \emph{ordering} of the notes.  This particular issue can be solved by using
% \cs{footnotemark} without argument, and manually adjusting the counter on
% subsequent calls to \cs{footnotetext}.  A good example of the technique is
% \url{https://tex.stackexchange.com/a/43694}.  True, a user may wish to
% specify the mark explicitly, but doesn't necessarily need to do it to solve
% the ordering issue.
%
% Multiple typesetting passes of content are much harder.  And they abound:
% the standard classes' \cs{caption} typesets the caption once, if it is
% short, but twice if it is longer than a line; \pkg{amsmath}'s math
% environments perform a measuring pass before actually typesetting the
% equations; \pkg{amsmath}'s \cs{text} macro runs the contents through
% \cs{mathchoice} (which typesets the contents four times) when in math mode;
% \pkg{tabularx} and \pkg{tabularray} also perform measuring passes of their
% tables; so does \pkg{csquotes}' blockquotes; and certainly more that I'm
% unaware.  A number of these places offer some one or another way to mitigate
% the issue: \pkg{amsmath}, \pkg{tabularx}, \pkg{csquotes} and (optionally)
% \pkg{tabularray} restore counter values after measuring steps; \pkg{amsmath}
% offers a boolean to indicate when it is a measuring pass; \pkg{csquotes}
% offers further handles.  But the standard \cs{caption} offers none, and
% neither does \pkg{amsmath}'s \cs{text} macro.  Well, the pkg{caption}
% package can disable the multiple passes for \cs{caption} with the option
% \opt{singlelinecheck}, but it is not reasonable to require it for our
% purposes, so we must assume the worst case.
%
% Enrico Gregorio is categorical in stating that \cs{endnotemark} and
% \cs{endnotetext} are required for \pkg{enotez} to handle \cs{caption}, which
% apparently it didn't offer originally: ``The package should implement
% \cs{endnotemark} and \cs{endnotetext} for this case.  According to the
% documentation, the author deems them to not be needed: he's wrong.''
% (\url{https://tex.stackexchange.com/a/314937}).  See also
% \url{https://tex.stackexchange.com/a/43794} and
% \url{https://tex.stackexchange.com/a/358207}.
%
% In this scenario, when there's no way around the multiple passes,
% \cs{footnotemark} can only handle the general case if used with an argument,
% precisely because it inhibits the stepping of the counter.  Otherwise the
% counter is stepped multiple times, and we'd get the wrong number (and mark).
% In some circumstances, if we know the number of passes is deterministic, we
% might get away by adjusting the counter manually (\cs{caption} may be dealt
% with this way: if we know it to be two lines, we can decrement the counter
% before it and get correct results, even hyperlinked).  But in cases which
% adjusting the counter is sufficient, end notes can be dealt with in the same
% way, and doesn't need the separation between ``mark'' and ``text''.  So,
% what is distinctive of the kernel's footnote apparatus, which allows it as
% much flexibility as one would like, is receiving an arbitrary number as
% argument and not stepping the counter.  And as far as \cs{footnotemark} and
% \cs{footnotetext} are concerned, the main point of the optional argument is
% really to ``manually establish the relation'' between the two of them.  So,
% if \emph{not stepping the counter} is what is needed to handle the general
% case, is it viable to do so? What would we loose in so doing?
%
% When receiving an arbitrary number as argument, as the kernel functionality
% for footnotes and other endnotes packages do, this value is expected to the
% printed as such, hence it must correspond to the \texttt{postnote} counter
% (in our case).  But this counter is in the hands of the user, and can be
% reset along the document, thus its uniqueness cannot be ensured.  But not
% stepping \texttt{postnote} is perfectly viable, as it just aims at storing
% how the mark is to be typeset.  However, not stepping the ID counter would
% complicate things considerably.  Not doing so implies we'd lose the
% connection we have between the ``mark'' and the corresponding ``text''.  We
% might add the ``text'' to the queue, but all the metadata would be lost,
% including the \pkg{hyperref} anchor, but really the set of data without
% which the kind of functionality offered would be nonviable, or severely
% hampered.  Not stepping \texttt{postnote} but stepping the ID counter also
% is not sufficient, because we'd get a note in duplicity.  We could naively
% think that a gap in the ID is not a problem, and just not add the duplicate
% to the queue.  But how could we tell the difference between a legitimate and
% an illegitimate step of the ID counter?
%
% I have not been able to devise a way to ``reconnect'' ``text'' and ``mark''
% in the absence of the unique ID counter.  The most promising idea was to
% have mandatory arguments to \cs{postnotemark} and \cs{postnotetext}
% receiving a \meta{label} which we could use to identify their counterparts,
% but I was not able to go through with this, and the attempts all increased
% complexity considerably.  It is not just a label/ref system, there's got to
% be a one-to-one correspondence between the sets, uniqueness has to be
% ensured on both sides, and there cannot be ``lone'' marks or texts (a
% bijection).  Besides, this label based system of identification would have
% to live side-by-side with the one based on the counter.  So, even if we'd
% have unique IDs, we wouldn't know beforehand in what form it comes.
% Considering the ID is used to build the variable name in which we store the
% note's information, this would also complicate things.
%
% Besides, there are ways to get things working with multiple passes without
% the ``mark''/``text'' partition.  As mentioned, there are a number of cases
% which offer some kind of ``handle'' or way to identify the multiple passes.
% \pkg{csquotes} has a dedicated hook that can be used.  \pkg{amsmath} sets
% the \texttt{measuring@} boolean (which \pkg{hyperref} also defines).  So,
% not all cases are as tricky as \cs{caption} or \cs{text}, and even that can
% be decently dealt with without a separation between ``mark'' and ``text''.
% Besides, in difficult cases, the package offers a \opt{nomark} option to
% \cs{postnote} to place a note, but typeset no mark.  Then we can typeset a
% mark with \cs{postnoteref} referring to a \cs{label} in the note of
% interest.  This would result in a correct mark without duplicity, and in a
% correct link from there to the note's text at \cs{printpostnotes}.  The
% drawback is that the placement of \cs{postnote} would be important, and
% results sensitive to it.  All the metadata is collected at the point of
% \cs{postnote}, anchor included, not at the point of \cs{postnoteref}.  So
% the consequences are a slightly off backlink, possibly imprecise metadata,
% etc.  Considering \pkg{hyperref} itself shies away completely from linking
% \cs{footnotemark} with an argument, I'd say there's some gain.
%
% The truth is there are some trade-offs, there's no ``ideal'' solution.
% Still, all in all, my judgment is that the unique ID counter is worth more
% than the inconveniences of an ocasional \texttt{\cs{postnote}[nomark]}
% referenced with \cs{postnoteref}, and even that should not be needed much.
% So, for the time being, until something else shakes this balance, I won't be
% offering \cs{postnotemark} and \cs{postnotetext}.
%
% \bigskip{}
%
% For the \pkg{hyperref} support for cross-references in \cs{postnote}, I've
% moved back and forth quite a lot.  One of the ideas I fancied was using
% \cs{refstepcounter} and let \pkg{hyperref} do its job.  But, since I want to
% have control of the anchor/destination name on both ``sides'', I'd have to
% set \cs{theHpostnote} locally before calling \cs{refstepcounter}, otherwise
% results might sensitive to user calls to \cs{counterwithin} (see
% \url{https://github.com/latex3/hyperref/issues/230}, thanks
% \contributor{Ulrike Fischer}).  However, even if that worked well for the
% default case, we still had to setup things manually, in case of a manually
% supplied mark.  All in all, I'm just calling \cs{stepcounter}, setting the
% relevant cross-reference variables once and setting the anchor manually.
%
%
% \bigskip{}
%
% \texttt{postnote} is the public, user facing, counter for \cs{postnote}.  It
% determines how the note's mark gets to be typeset.  It can be reset, set,
% and have its printed representation changed.  Of course, whether those are
% meaningful is up to the user.
%
%    \begin{macrocode}
\newcounter { postnote }
%    \end{macrocode}
%
% \begin{macro}[int]
%   {
%     \g_@@_note_id_int ,
%     \l_postnotes_note_id_tl ,
%     \g_@@_queue_seq ,
%     \l_@@_counteraux_step_int ,
%     \l_@@_mark_typeset_tl ,
%     \l_@@_note_set_labels_tl ,
%   }
%   \cs{g_@@_note_id_int} is the internal, unique counter which provides the
%   ID number of each note.  It ties ``mark'' and ``text'' together, is also
%   the connection between each note and its data, including the content,
%   which is stored in a property list named according to \cs{@@_data_name:n}
%   and the ID number.  \cs{l_postnotes_note_id_tl} is a convenience variable
%   storing the counter's value.  \cs{g_@@_queue_seq} stores the sequence of
%   notes' IDs to be processed by the next call of \cs{printpostnotes}.
%    \begin{macrocode}
\int_new:N \g_@@_note_id_int
\tl_new:N \l_postnotes_note_id_tl
\tl_set:Nn \l_postnotes_note_id_tl { \int_use:N \g_@@_note_id_int }
\seq_new:N \g_@@_queue_seq
\int_new:N \l_@@_counteraux_step_int
\tl_new:N \l_@@_mark_typeset_tl
\tl_new:N \l_@@_note_set_labels_tl
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}[int]{\postnote}
%   Provide \cs{postnote}.
%   \begin{syntax}
%     \cs{postnote}\oarg{options}\marg{note text}
%   \end{syntax}
%    \begin{macrocode}
\NewDocumentCommand \postnote { O { } +m }
  { \@@_note:nn {#1} {#2} }
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\@@_note:nn}
%   The internal version of \cs{postnote}.  The \texttt{postnotes/note/begin}
%   hook is meant to provide a place from where some additional setup for the
%   note can be performed.  This is being used for adding support for some
%   features/packages, but can also be used, for example, to add an extra
%   local property for \pkg{zref}.
%   \begin{syntax}
%     \cs{@@_note:nn} \oarg{options} \marg{note content}
%   \end{syntax}
%    \begin{macrocode}
\NewHook { postnotes/note/begin }
\cs_new_protected:Npn \@@_note:nn #1#2
  {
    \group_begin:
      \keys_set:nn { postnotes/note } {#1}
      \bool_if:NT \l_@@_nomark_bool { \@bsphack }
      \@@_inhibit_note:F
        {
          \int_gincr:N \g_@@_note_id_int
          \tl_if_empty:NTF \l_@@_mark_tl
            {
              \stepcounter { postnote }
              \int_set:Nn \l_@@_counteraux_step_int { 1 }
              \bool_if:NT \g_@@_counteraux_bool
                {
                  \exp_args:NNe \prop_gpop:NnNT \g_@@_counteraux_prop
                    { \l_postnotes_note_id_tl } \l_@@_tmpa_tl
                    { \int_set:Nn \c@postnote { \l_@@_tmpa_tl } }
                  \tl_clear:N \l_@@_tmpa_tl
                }
              \tl_set:Ne \l_@@_mark_tl { \thepostnote }
            }
            { \int_set:Nn \l_@@_counteraux_step_int { 0 } }
          \UseHook { postnotes/note/begin }
          \seq_gput_right:Ne \g_@@_queue_seq
            { \l_postnotes_note_id_tl }
          \cs_set:Npn \@currentcounter { postnote }
          \cs_set:Npe \@currentlabel { \p@postnote \l_@@_mark_tl }
          \@@_store:nn { \l_postnotes_note_id_tl } {#2}
          \tl_set_eq:NN \l_@@_mark_typeset_tl \l_@@_mark_tl
%    \end{macrocode}
% Prefer \opt{label} for typesetting measuring passes, if available, see
% comments at \cs{@@_inhibit_note:F}.
%    \begin{macrocode}
          \bool_lazy_or:nnT
            { \g_@@_counteraux_bool }
            { \l_@@_maybe_multi_bool }
            {
              \bool_lazy_and:nnT
                { ! \g_@@_firstrun_bool }
                {
                  ! \cs_if_exist_p:c
                    { \c_@@_ref_prefix_tl @ mark @ \l_postnotes_note_id_tl }
                }
                { \@@_get_label_if_exist:N \l_@@_mark_typeset_tl }
            }
          \tl_set:Nn \l_@@_note_set_labels_tl
            {
              \MakeLinkTarget* { postnote. \l_postnotes_note_id_tl .mark }
              \@@_set_mark_page_label:ee { \l_postnotes_note_id_tl }
                { \int_use:N \l_@@_counteraux_step_int }
              \@@_set_user_labels:
            }
          \bool_if:NTF \l_@@_nomark_bool
            {
              \tag_socket_use:n { postnotes/nomark/begin }
              \l_@@_note_set_labels_tl
              \tag_socket_use:n { postnotes/nomark/end }
            }
            {
              \@@_typeset_mark:eVN
                { \l_postnotes_note_id_tl } \l_@@_mark_typeset_tl
                \l_@@_note_set_labels_tl
            }
        }
      \bool_if:NT \l_@@_nomark_bool { \@esphack }
    \group_end:
  }
%    \end{macrocode}
% \end{macro}
%
%
% Options for \cs{postnote}.
%
%    \begin{macrocode}
\tl_new:N \l_@@_mark_tl
\bool_new:N \l_@@_nomark_bool
\fp_new:N \l_@@_sort_num_fp
\str_new:N \l_@@_note_label_str
\bool_new:N \l_@@_manual_sortnum_bool
\keys_define:nn { postnotes/note }
  {
    markstr .tl_set:N = \l_@@_mark_tl ,
    markstr .value_required:n = true ,
    sortnum .code:n =
      {
        \fp_set:Nn \l_@@_sort_num_fp {#1}
        \bool_set_true:N \l_@@_manual_sortnum_bool
      } ,
    sortnum .value_required:n = true ,
    mark .meta:n =
      {
        markstr = {#1} ,
        sortnum = {#1} ,
      } ,
    mark .value_required:n = true ,
    nomark .bool_set:N = \l_@@_nomark_bool ,
    nomark .default:n = true ,
    label .str_set:N = \l_@@_note_label_str ,
    label .value_required:n = true ,
    maybemulti .bool_set:N = \l_@@_maybe_multi_bool ,
    maybemulti .default:n = true ,
  }
%    \end{macrocode}
%
%
% \begin{macro}{\@@_inhibit_note:TF}
%   In contexts of multiple passes of content, it may be needed, or preferred,
%   to inhibit the note altogether to avoid side effects and duplicity.  This
%   conditional, obviously, will always return the true branch unless
%   something is done in the \texttt{postnotes/note/inhibit} hook.  This hook
%   is meant to handle support for packages or features which may justify note
%   inhibition, and the code there should set \cs{l_@@_inhibit_note_bool},
%   \cs{l_@@_print_plain_mark_bool} and
%   \cs{l_@@_print_plain_mark_stepcounter_bool} as appropriate to the case.
%    \begin{macrocode}
\bool_new:N \l_@@_inhibit_note_bool
\bool_new:N \l_@@_print_plain_mark_bool
\bool_new:N \l_@@_print_plain_mark_stepcounter_bool
\NewHook { postnotes/note/inhibit }
\prg_new_protected_conditional:Npnn \@@_inhibit_note: { F }
  {
    \bool_set_false:N \l_@@_inhibit_note_bool
    \bool_set_false:N \l_@@_print_plain_mark_bool
    \bool_set_false:N \l_@@_print_plain_mark_stepcounter_bool
    \UseHook { postnotes/note/inhibit }
%    \end{macrocode}
% Printing a plain mark here may be needed because, if we are inhibiting the
% note in a ``measuring context'' and omit it completely, the measuring being
% performed will be off by the size of the mark.  So, to ensure the measuring
% can be done correctly, we place the mark.  What to do with the counter
% itself, depends on the situation.  In places that are known to restore the
% counter values after the measuring pass, we can let the counter be stepped.
% And, actually we should do so, for example, in a \env{tabularx} with
% multiple postnotes, if we don't step the counter, all the measuring will be
% done with the number of the first note.  Otherwise, we don't actually step
% the counter but, to typeset correctly the mark that would be printed if the
% counter had been stepped, we increment \cs{c@postnote} locally and grouped,
% and smuggle \cs{thepostnote} out of the group.
%    \begin{macrocode}
    \bool_lazy_all:nT
      {
        { \l_@@_inhibit_note_bool }
        { \l_@@_print_plain_mark_bool }
        { ! \l_@@_nomark_bool }
      }
      {
        \tl_if_empty:NTF \l_@@_mark_tl
          {
            \bool_if:NTF \l_@@_print_plain_mark_stepcounter_bool
              {
                \stepcounter { postnote }
                \tl_set:Ne \l_@@_mark_typeset_tl { \thepostnote }
              }
              {
                \group_begin:
                  \int_incr:N \c@postnote
                  \exp_args:NNNe
                    \group_end:
                    \tl_set:Nn \l_@@_mark_typeset_tl { \thepostnote }
              }
%    \end{macrocode}
% If the note has a \opt{label}, use a cross-reference to that as the mark
% instead.  In principle, the procedure above is expected to work reasonably
% well for cases where we know whether we are in a measuring pass or not, and
% how it handles the counters (if it restores counters or not).  This is true
% though, only if we are going in the expansion order of the document.  If we
% are using the \opt{counteraux} option, the mere sequence of the notes is no
% longer an indicator of who is a measuring pass of who, indeed the measuring
% pass does not even get to the \file{.aux} file.  If the label exists,
% though, it is \emph{known to be right} regardless of the case, since it
% belongs to the pass which actually gets typeset.  Hence, if we have a label,
% it is more general and more reliable: use it.
%    \begin{macrocode}
            \@@_get_label_if_exist:N \l_@@_mark_typeset_tl
          }
          { \tl_set_eq:NN \l_@@_mark_typeset_tl \l_@@_mark_tl }
        \group_begin:
          \socket_assign_plug:nn { tagsupport/postnotes/multisep/begin } { noop }
          \socket_assign_plug:nn { tagsupport/postnotes/multisep/end } { noop }
          \@@_typeset_mark_wrapper:nnn
            { \@@_make_mark:Vnn \l_@@_mark_typeset_tl { } { } }
            { } { }
        \group_end:
      }
    \bool_if:NTF \l_@@_inhibit_note_bool
      { \prg_return_true:  }
      { \prg_return_false: }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_get_label_if_exist:N}
%   \begin{syntax}
%     \cs{@@_get_label_if_exist:N} \meta{\cs{l_@@_mark_tl}}
%   \end{syntax}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_get_label_if_exist:N #1
  {
    \str_if_empty:NTF \l_@@_note_label_str
      {
        \str_if_empty:NF \l_@@_note_zlabel_str
          {
            \exp_args:NV \zref@ifrefundefined \l_@@_note_zlabel_str
              { }
              {
                \exp_args:NV \zref@ifrefcontainsprop
                  \l_@@_note_zlabel_str
                  { postnote@mark }
                  {
                    \exp_args:NNNo \exp_args:NNo \tl_set:Nn #1
                      {
                        \zref@extract
                          { \l_@@_note_zlabel_str } { postnote@mark }
                      }
                  }
                  { }
              }
          }
      }
      {
        \exp_args:Ne \property_if_recorded:nnT
          { postnotes@ \l_@@_note_label_str }
          { postnotes/mark }
          {
            \tl_set:Ne #1
              {
                \property_ref:ee
                  { __postnotes_ \l_@@_note_label_str } { postnotes/mark }
              }
          }
      }
  }
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}
%   {
%     \@@_typeset_mark:nnN ,
%     \@@_typeset_mark_wrapper:nnn ,
%   }
%   Auxiliary functions for mark typesetting in \cs{@@_note:nn}.
%   \cs{@@_typeset_mark_wrapper:nnn} is based on the definition of
%   \cs{@footnotemark} in the kernel.
%   \begin{syntax}
%     \cs{@@_typeset_mark:nnN} \Arg{note id} \Arg{mark} \Arg{labels}
%     \cs{@@_typeset_mark_wrapper:nnn} \Arg{mark}
%     ~~\Arg{begin tagging} \Arg{end tagging}
%   \end{syntax}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_typeset_mark:nnN #1#2#3
  {
    \@@_typeset_mark_wrapper:nnn
      {
        #3
        \bool_if:NTF \l_@@_hyperlink_bool
          {
            \@@_make_mark:nnn {#2}
              { \hyper@linkstart { link } { postnote. #1 .text } }
              { \hyper@linkend }
          }
          { \@@_make_mark:nnn {#2} { } { } }
      }
      { \tag_socket_use:n { postnotes/mark/begin } }
      { \tag_socket_use:n { postnotes/mark/end }   }
  }
\cs_generate_variant:Nn \@@_typeset_mark:nnN { eVN }
\tl_new:N \l_@@_saved_spacefactor_tl
\cs_new_protected:Npn \@@_typeset_mark_wrapper:nnn #1#2#3
  {
    \mode_leave_vertical:
    \mode_if_horizontal:T
      {
        \tl_set:Ne \l_@@_saved_spacefactor_tl
          { \int_use:N \spacefactor }
        \@@_multiple_check:
        \nobreak
      }
    #2 % begin tagging socket
    #1 % mark
    #3 % end tagging socket
    \@@_multiple_prepare:
    \mode_if_horizontal:T
      { \spacefactor \l_@@_saved_spacefactor_tl }
    \scan_stop:
  }
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\@@_set_user_labels:}
%   Auxiliary function for user label setting in \cs{@@_note:nn}.  Supports
%   the \opt{label} and \opt{zlabel} options of \cs{postnote}.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_set_user_labels:
  {
    \str_if_empty:NF \l_@@_note_label_str
      {
        \exp_args:NV \label \l_@@_note_label_str
        \property_record:ee { __postnotes_ \l_@@_note_label_str }
          { postnotes/mark }
      }
    \str_if_empty:NF \l_@@_note_zlabel_str
      { \exp_args:NV \zlabel \l_@@_note_zlabel_str }
  }
\property_new:nnnn { postnotes/mark } { now } { } { \l_@@_mark_tl }
%    \end{macrocode}
% \end{macro}
%
%
% \section{\cs{postnoteref}}
%
% \begin{macro}[int]{\postnoteref}
%   Provide \cs{postnoteref}.
%   \begin{syntax}
%     \cs{postnoteref}\meta{*}\marg{label}
%   \end{syntax}
%    \begin{macrocode}
\NewDocumentCommand \postnoteref { s m }
  { \@@_note_ref:nn {#1} {#2} }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_note_ref:nn}
%   The internal version of \cs{postnoteref}.
%   \begin{syntax}
%     \cs{@@_note_ref:nn} \Arg{star bool} \Arg{label}
%   \end{syntax}
%    \begin{macrocode}
\tl_new:N \l_@@_note_ref_label_tl
\cs_new_protected:Npn \@@_note_ref:nn #1#2
  {
    \group_begin:
      \tl_set:Nn \l_@@_note_ref_label_tl {#2}
      \@@_typeset_mark_wrapper:nnn
        {
          \bool_lazy_and:nnTF
            { ! #1 }
            { \l_@@_hyperlink_bool }
            {
              \hyperref [#2]
                { \@@_make_mark:nnn { \ref*{#2} } { } { } }
            }
            { \@@_make_mark:nnn { \ref*{#2} } { } { } }
        }
        { \tag_socket_use:n { postnotes/postnoteref/begin } }
        { \tag_socket_use:n { postnotes/postnoteref/end }   }
    \group_end:
  }
%    \end{macrocode}
% \end{macro}
%
%
% \section{\cs{postnotesection}}
%
% \begin{macro}[int]{\postnotesection}
%   Provide \cs{postnotesection}.
%   \begin{syntax}
%     \cs{postnotesection}\oarg{options}\marg{section content}
%   \end{syntax}
%    \begin{macrocode}
\NewDocumentCommand \postnotesection { O { } +m }
  {
    \@bsphack
    \@@_section:nn {#1} {#2}
    \@esphack
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_section:nn}
%   The internal version of \cs{postnotesection}.
%   \begin{syntax}
%     \cs{@@_section:nn} \Arg{options} \Arg{content}
%   \end{syntax}
%    \begin{macrocode}
\int_new:N \g_@@_sectid_int
\cs_new_protected:Npn \@@_section:nn #1#2
  {
    \group_begin:
      \int_gincr:N \g_@@_sectid_int
      \int_gincr:N \g_@@_note_id_int
      \seq_gput_right:Ne \g_@@_queue_seq { \l_postnotes_note_id_tl }
      \tl_gclear:N \g_@@_section_name_tl
      \keys_set:nn { postnotes/section } {#1}
      \@@_set_section_page_label:e { \l_postnotes_note_id_tl }
      \bool_if:NTF \l_@@_section_exp_bool
        { \@@_store_section:ne { \l_postnotes_note_id_tl } {#2} }
        { \@@_store_section:nn { \l_postnotes_note_id_tl } {#2} }
    \group_end:
  }
%    \end{macrocode}
% \end{macro}
%
%
% Options for \cs{postnotesection}.  Actually, I would have preferred to use
% ``label'' for the \opt{name} option, but I feared I might need it further
% down the road for the traditional meaning.
%
%    \begin{macrocode}
\tl_new:N \g_@@_section_name_tl
\bool_new:N \l_@@_section_exp_bool
\keys_define:nn { postnotes/section }
  {
    name .tl_gset:N = \g_@@_section_name_tl ,
    name .value_required:n = true ,
    exp .bool_set:N = \l_@@_section_exp_bool ,
    exp .initial:n = false ,
    exp .default:n = true ,
  }
%    \end{macrocode}
%
%
% \section{\cs{printpostnotes}}
%
% \begin{macro}[int]{\printpostnotes}
%   Provide \cs{printpostnotes}.
%   \begin{syntax}
%     \cs{printpostnotes}
%   \end{syntax}
%    \begin{macrocode}
\NewDocumentCommand \printpostnotes { }
  { \@@_print_notes: }
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}[int]
%   {
%     \pnthechapter ,
%     \pnthesection ,
%     \pnthechapternextnote ,
%     \pnthesectionnextnote ,
%     \pnthepage ,
%     \pnidnextnote ,
%   }
%   User facing variables, aimed at making available some of the notes' and
%   sections' metadata for the user at specific contexts.
%    \begin{macrocode}
\tl_new:N \pnthechapter
\tl_new:N \pnthesection
\tl_new:N \pnidnextnote
\tl_new:N \pnthechapternextnote
\tl_new:N \pnthesectionnextnote
\tl_new:N \pnthepage
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[int]
%   {
%     \g_@@_print_postnotes_int ,
%     \g_@@_print_queue_seq ,
%     \l_postnotes_print_note_id_tl ,
%     \l_@@_print_note_id_next_tl ,
%     \l_@@_print_counter_tl ,
%     \l_@@_print_mark_tl ,
%     \l_@@_print_typeset_mark_tl ,
%     \l_@@_print_type_curr_tl ,
%     \l_@@_print_type_next_tl ,
%     \l_@@_print_type_prev_tl ,
%     \l_@@_print_content_tl ,
%     \l_@@_clear_queue_seq ,
%   }
%   Auxiliary variables for \cs{@@_print_notes:}.
%    \begin{macrocode}
\int_new:N \g_@@_print_postnotes_int
\seq_new:N \g_@@_print_queue_seq
\tl_new:N \l_postnotes_print_note_id_tl
\tl_new:N \l_@@_print_note_id_next_tl
\tl_new:N \l_@@_print_counter_tl
\tl_new:N \l_@@_print_mark_tl
\tl_new:N \l_@@_print_typeset_mark_tl
\tl_new:N \l_@@_print_type_curr_tl
\tl_new:N \l_@@_print_type_next_tl
\tl_new:N \l_@@_print_type_prev_tl
\tl_new:N \l_@@_print_content_tl
\seq_new:N \l_@@_clear_queue_seq
%    \end{macrocode}
% \end{macro}
%
%
% \cs{@@_print_notes:}' hooks.  Both meant at providing points of entry for
% additional setup, specially to add support to packages and features which
% require it.  The \texttt{postnotes/print/begin} hook is run early in
% \cs{@@_print_notes:} and only once per call, after the user options have
% been processed.  The \texttt{postnotes/print/note/begin} hook is run once
% for each note, at the point where environment variables are being set or
% restored, before the typesetting of either the mark or the text, but within
% a group of its own of each note.
%
%    \begin{macrocode}
\NewHook { postnotes/print/begin }
\NewHook { postnotes/print/note/begin }
%    \end{macrocode}
%
%
% The \texttt{postnotetext} is a counter used to restore the original value of
% \texttt{postnote} at the time of printing, for the purposes of
% cross-referencing, it should be different from \texttt{postnote} if a note
% may occur inside \cs{printpostnotes}.  The \texttt{postnotesection} is a
% counter which is stepped for every postnote section which gets to be
% actually typeset.  It's aim is to provide a valid ``enclosing counter'' to
% \texttt{postnote} in the context of \cs{printpostnotes}.  Since we don't
% know where \texttt{postnote} may have been reset along the document, in the
% general case, we can't rely on any other preexisting counter.  This means
% that the particular value of \texttt{postnotesection} is of little practical
% meaning, it really is just meant to provide recognizable ``bounds'' for
% \texttt{postnote} along the printing of the notes.  Indeed, it is
% initialized to a very high value (larger than the conceivable number of
% postnote sections in a document), so that ``marks'' and ``texts'' don't mix
% in the same reference list, which would occur if the enclosing counters of
% both belonged to the same range, and with somewhat arbitrary results, since
% we cannot ensure the step of the enclosing counter along the document
% matches \texttt{postnotesection}.  This is actually a tricky problem from
% the cross-referencing standpoint: two different things, which should be of
% the same type, are reset along the document, but shouldn't really be mixed
% together.  They are both \LaTeXe{} counters, since they may be required
% externally.  Their main intended use case is to support \pkg{zref-clever},
% but in principle they can be of general use.
%
%    \begin{macrocode}
\newcounter { postnotetext }
\newcounter { postnotesection }
\setcounter { postnotesection } { 10000 }
%    \end{macrocode}
%
%
% \begin{macro}{\@@_print_notes:}
%   The internal version of \cs{printpostnotes}.
%   \begin{syntax}
%     \cs{@@_print_notes:}
%   \end{syntax}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_print_notes:
  {
    \group_begin:
      \int_gincr:N \g_@@_print_postnotes_int
      \@@_split_labelseq:
%    \end{macrocode}
% We make the cut at this point.  \cs{g_@@_print_queue_seq} is stored won't
% receive any more notes for the duration of this call of \cs{printpostnotes},
% any notes added to the queue from this point on belong to the next call of
% \cs{printpostnotes}.
%    \begin{macrocode}
      \bool_lazy_and:nnTF
        { \g_@@_counteraux_bool }
        { ! \g_@@_firstrun_bool }
        {
          \seq_gset_eq:NN \g_@@_print_queue_seq
            \g_@@_print_labelseq_queue_seq
        }
        {
          \seq_gset_eq:NN \g_@@_print_queue_seq
            \g_@@_queue_seq
        }
      \seq_set_eq:NN \l_@@_clear_queue_seq \g_@@_print_queue_seq
      \seq_gclear:N \g_@@_queue_seq
%    \end{macrocode}
% The  purpose of this label is to provide a point for splitting the labelseq
% with the \opt{counteraux} option.  It only needs to exist, it doesn't even
% store the page value.  The \cs{@@_set_print_page_label:e} done at
% \cs{@@_set_headers_vars_first:} right below does not suffice for this
% purpose for two reasons.  It won't be set if the queue is empty (or not yet
% populated), and also it comes after the heading (as it must), which means
% \cs{postnotesection}s added through hooks to it will come before it.
%    \begin{macrocode}
      \@@_set_pre_print_label:e
        { \int_use:N \g_@@_print_postnotes_int }
      \seq_if_empty:NTF \g_@@_print_queue_seq
        { \msg_warning:nn { postnotes } { empty-printpostnotes } }
        {
          \pnheading
          \UseHook { postnotes/print/begin }
          \tl_set:Nn \l_@@_print_type_prev_tl { open }
          \@@_check_duplicates:N \g_@@_print_queue_seq
          \@@_sort_queue:N \g_@@_print_queue_seq
          \@@_check_floats:N \g_@@_print_queue_seq
          \bool_gset_true:N \g_@@_header_vars_next_bool
          \@@_get_headers_data:N \g_@@_print_queue_seq
          \@@_set_headers_vars_first:
%    \end{macrocode}
% Ensure the first note after a heading has paragraph indentation when
% \opt{listenv} is \texttt{none}.  \pkg{endnotes} uses a workaroundish
% solution in \cs{enoteheading}, setting a box and then skipping back a line.
% Enrico Gregorio is correct, though, in criticizing it at
% \url{https://tex.stackexchange.com/q/575905#comment1450213_575915}, and
% suggests the use of \cs{@afterindenttrue}, which is what \pkg{indentfirst}
% does (we do the same, just locally).
%    \begin{macrocode}
          \bool_if:NF \l_@@_print_as_list_bool
            {
              \cs_set_eq:NN \@afterindentfalse \@afterindenttrue
              \@afterindenttrue
            }
          \bool_until_do:nn { \seq_if_empty_p:N \g_@@_print_queue_seq }
            {
              \seq_gpop_left:NN \g_@@_print_queue_seq
                \l_postnotes_print_note_id_tl
              \@@_prop_get:nnN { \l_postnotes_print_note_id_tl }
                { type } \l_@@_print_type_curr_tl
              \tl_if_eq:NnTF \l_@@_print_type_curr_tl { section }
                { % type_curr = `section'
                  \seq_if_empty:NTF \g_@@_print_queue_seq
                    {
                      \tl_set:Nn \l_@@_print_note_id_next_tl { noid }
                      \tl_set:Nn \l_@@_print_type_next_tl { close }
                    }
                    {
                      \seq_get_left:NN \g_@@_print_queue_seq
                        \l_@@_print_note_id_next_tl
                      \@@_prop_get:nnN
                        { \l_@@_print_note_id_next_tl }
                        { type } \l_@@_print_type_next_tl
                    }
%    \end{macrocode}
% We only process the entry if \texttt{type_next} is \texttt{note}: here are
% skipped empty sections.
%    \begin{macrocode}
                  \tl_if_eq:NnT \l_@@_print_type_next_tl { note }
                    {
                      \stepcounter { postnotesection }
                      \group_begin:
                        \@@_prop_get:nnN
                          { \l_postnotes_print_note_id_tl }
                          { thechapter } \pnthechapter
                        \@@_prop_get:nnN
                          { \l_postnotes_print_note_id_tl }
                          { thesection } \pnthesection
                        \tl_set:NV \pnidnextnote
                          \l_@@_print_note_id_next_tl
                        \@@_prop_get:nnN
                          { \l_@@_print_note_id_next_tl }
                          { thechapter } \pnthechapternextnote
                        \@@_prop_get:nnN
                          { \l_@@_print_note_id_next_tl }
                          { thesection } \pnthesectionnextnote
                        \@@_prop_get:nnN
                          { \l_postnotes_print_note_id_tl }
                          { content } \l_@@_print_content_tl
                        \l_@@_print_content_tl
                      \group_end:
%    \end{macrocode}
% Set \texttt{type_prev} for the next iteration.
%    \begin{macrocode}
                      \tl_set:NV \l_@@_print_type_prev_tl
                        \l_@@_print_type_curr_tl
                    }
                }
                { % type_curr = `note'
                  \seq_if_empty:NTF \g_@@_print_queue_seq
                    {
                      \tl_set:Nn \l_@@_print_note_id_next_tl { noid }
                      \tl_set:Nn \l_@@_print_type_next_tl { close }
                    }
                    {
                      \seq_get_left:NN \g_@@_print_queue_seq
                        \l_@@_print_note_id_next_tl
                      \@@_prop_get:nnN
                        { \l_@@_print_note_id_next_tl }
                        { type } \l_@@_print_type_next_tl
                    }
                  \tl_if_eq:NnF \l_@@_print_type_prev_tl { note }
                    {
                      \bool_if:NTF \l_@@_print_as_list_bool
                        { \exp_args:NV \begin \l_@@_print_env_tl }
                        { \group_begin: }
                      \tag_socket_use:n { postnotes/printlist/begin }
                      \l_@@_print_format_tl
                    }
                  \group_begin:
                    \UseHook { postnotes/print/note/begin }
                    \@@_get_pageref:Ne \pnthepage
                      { mark@ \l_postnotes_print_note_id_tl }
                    \@@_prop_get:nnN
                      { \l_postnotes_print_note_id_tl }
                      { mark } \l_@@_print_mark_tl
                    \@@_prop_get:nnN
                      { \l_postnotes_print_note_id_tl }
                      { counter } \l_@@_print_counter_tl
                    \@@_prop_get:nnN
                      { \l_postnotes_print_note_id_tl }
                      { content } \l_@@_print_content_tl
                    \cs_set:Npn \@currentcounter { postnotetext }
                    \int_set:Nn \c@postnotetext
                      { \l_@@_print_counter_tl }
                    \cs_set:Npe \@currentlabel
                      { \p@postnote \l_@@_print_mark_tl }
                    \tl_set:Nn \l_@@_print_typeset_mark_tl
                      {
                        \tag_socket_use:n { postnotes/printmark/begin }
                        \MakeLinkTarget*
                          { postnote. \l_postnotes_print_note_id_tl .text }
                        \@@_set_text_page_label:e
                          { \l_postnotes_print_note_id_tl }
                        \l_@@_pre_textmark_tl
                        \@@_typeset_text_mark:eV
                          { \l_postnotes_print_note_id_tl }
                          \l_@@_print_mark_tl
                        \l_@@_post_textmark_tl
                        \tag_socket_use:n { postnotes/printmark/end }
                      }
%    \end{macrocode}
% Note that the placement of the tagging socket for the list case may depend
% on the tagging structure, in other words, on the content of the socket.  It
% currently does nothing for the list case, so I've placed it in the
% ``potentially most useful place''.  Review this if the content changes.
% Leave vertical mode after \cs{item} for the list case to avoid ``perhaps a
% missing \cs{item}'' error for empty notes (see
% \file{pn-bug-empty-postnote01.lvt}).  And leave vertical mode before the
% note (and the tagging socket) for \opt{listenv=none} (see
% \url{https://github.com/gusbrs/postnotes/issues/8#issuecomment-2429501962},
% thanks \contributor{Ulrike Fischer}).
%    \begin{macrocode}
                    \bool_if:NTF \l_@@_print_as_list_bool
                      {
                        \item
                          [
                            \tag_socket_use:n { postnotes/printnote/begin }
                            \l_@@_print_typeset_mark_tl
                          ]
                        \mode_leave_vertical:
                      }
                      {
                        \mode_leave_vertical:
                        \tag_socket_use:n { postnotes/printnote/begin }
                        \l_@@_print_typeset_mark_tl
                      }
                    \tag_socket_use:n { postnotes/printtext/begin }
                    \l_@@_print_content_tl
                    \tag_socket_use:n { postnotes/printtext/end }
                    \tag_socket_use:n { postnotes/printnote/end }
                    \l_@@_post_printnote_tl
                  \group_end:
                  \tl_if_eq:NnF \l_@@_print_type_next_tl { note }
                    {
                      \tag_socket_use:n { postnotes/printlist/end }
%    \end{macrocode}
% Ensure \cs{par} at the end of \cs{printpostnotes} (see
% \url{https://github.com/u-fischer/tagpdf/issues/68#issuecomment-1587343876},
% thanks \contributor{Ulrike Fischer}).
%    \begin{macrocode}
                      \bool_if:NTF \l_@@_print_as_list_bool
                        {
                          \exp_args:NV \end \l_@@_print_env_tl
                          \par
                        }
                        {
                          \par
                          \group_end:
                        }
                    }
%    \end{macrocode}
% Set \texttt{type_prev} for the next iteration.
%    \begin{macrocode}
                  \tl_set:NV \l_@@_print_type_prev_tl
                    \l_@@_print_type_curr_tl
                }
            }
          \AddToHookNext { shipout/after }
            { \bool_gset_false:N \g_@@_header_vars_next_bool }
%    \end{macrocode}
% We won't use the variables anymore, clear them to reduce memory usage.
%    \begin{macrocode}
          \seq_map_inline:Nn \l_@@_clear_queue_seq
            { \@@_prop_gclear:n { ##1 } }
        }
    \group_end:
  }
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
\msg_new:nnn { postnotes } { empty-printpostnotes }
  { Empty~'\iow_char:N\\printpostnotes'~\msg_line_context:. }
%    \end{macrocode}
%
%
% \begin{macro}{\@@_typeset_text_mark:nn}
%   Auxiliary function for mark typesetting in \cs{@@_print_notes:}.
%   \begin{syntax}
%     \cs{@@_typeset_text_mark:nn} \Arg{note id} \Arg{mark}
%   \end{syntax}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_typeset_text_mark:nn #1#2
  {
    \bool_lazy_and:nnTF
      { \l_@@_hyperlink_bool }
      { \l_@@_backlink_bool  }
      {
        \@@_make_text_mark:nnn {#2}
          { \hyper@linkstart { link } { postnote. #1 .mark } }
          { \hyper@linkend }
      }
      { \@@_make_text_mark:nnn {#2} { } { } }
  }
\cs_generate_variant:Nn \@@_typeset_text_mark:nn { eV }
%    \end{macrocode}
% \end{macro}
%
%
% \subsection*{Print auxiliary}
%
% The conditions used to split \cs{g_@@_labelseq_seq} are subtly different
% depending on whether we are using \cs{g_@@_counteraux_bool} or not.  In the
% standard case, the numbering of the floats are set at ``expansion time'', so
% they belong where they are set.  With \opt{counteraux}, the numbering of
% floats are set at ``shipout time'', so they belong where they are typeset.
% In other words, with \opt{counteraux} notes on floats can cross the
% boundaries of \cs{printpostnotes}, while without it, they must not.
% Furthermore, the purpose of \cs{g_@@_labelseq_seq} is different in each
% case.  With \opt{counteraux} it is used to build the actual print queue,
% while in the standard case it is only used in \cs{@@_check_floats:N}.
% Therefore, with \opt{counteraux} the cut is made at the place the preprint
% label for the current \cs{printpostnotes} is found, while in the standard
% case, \cs{g_@@_note_id_int} is used directly to distribute the elements
% between the current \cs{printpostnotes} and future ones.
%
%
% \begin{macro}{\@@_split_labelseq:}
%    \begin{macrocode}
\seq_new:N \g_@@_print_labelseq_queue_seq
\cs_new_protected:Npn \@@_split_labelseq:
  {
    \group_begin:
      \seq_clear:N \l_@@_tmpa_seq
      \seq_clear:N \l_@@_tmpb_seq
      \bool_if:NTF \g_@@_counteraux_bool
        {
          \tl_set:Ne \l_@@_tmpa_tl
            { { preprint } { \int_use:N \g_@@_print_postnotes_int } }
%    \end{macrocode}
% The preprint label of a \cs{printpostnotes} at the end of the document may
% not have been written: if it's empty, it may not be shipped out at all.
% But, since it's a counter, stepped sequentially and not floating, even if it
% is transitorily missing, it will be at the end.  In other words, if this one
% is not found, there will be no subsequent preprints in the sequence.
%    \begin{macrocode}
          \seq_if_in:NVF \g_@@_labelseq_seq \l_@@_tmpa_tl
            { \seq_gput_right:NV \g_@@_labelseq_seq \l_@@_tmpa_tl }
          \bool_do_until:nn
            { \tl_if_eq_p:NN \l_@@_tmpb_tl \l_@@_tmpa_tl }
            {
              \seq_gpop_left:NN \g_@@_labelseq_seq \l_@@_tmpb_tl
              \str_case:enT
                { \tl_item:Nn \l_@@_tmpb_tl { 1 } }
                {
                  { mark }    { }
                  { section } { }
                }
                {
%    \end{macrocode}
% If the id of the labelseq item is larger than the current note id, we don't
% have data for the note at this point, and cannot print it.  Period.  Now,
% usually this will occur due to transitory effects.  But it is theoretically
% possible that a float is sent to the top of the page and gets typeset before
% a ``future \cs{printpostnotes}''.  So what we cannot print, we give back to
% the label sequence of the next \cs{printpostnotes}.  If they are transitory,
% they will eventually go away.  If they are not, better to keep them with the
% wrong numbering than dropping it altogether.  Alas, there's nothing else we
% could do, short of writing the whole data to the \file{.aux} file, which is
% clearly not worth this corner case.
%    \begin{macrocode}
                  \int_compare:nNnTF
                    { \tl_item:Nn \l_@@_tmpb_tl { 2 } }
                    >
                    { \g_@@_note_id_int }
                    {
                      \seq_put_right:Ne \l_@@_tmpb_seq
                        \l_@@_tmpb_tl
                    }
                    {
                      \seq_put_right:Ne \l_@@_tmpa_seq
                        { \tl_item:Nn \l_@@_tmpb_tl { 2 } }
                    }
                }
%    \end{macrocode}
% No need for the \texttt{F} branch of \cs{str_case:enT}, at this point the
% preprint of past \cs{printpostnotes} can no longer be here, and we don't go
% further than the current one.  In theory, we could even go without
% \cs{str_case:enT}, but let's play safe and keep the function robust against
% future changes of the code.
%    \begin{macrocode}
            }
          \seq_gset_eq:NN \g_@@_print_labelseq_queue_seq
            \l_@@_tmpa_seq
          \seq_concat:NNN \l_@@_tmpa_seq \l_@@_tmpb_seq
            \g_@@_labelseq_seq
          \seq_gset_eq:NN \g_@@_labelseq_seq \l_@@_tmpa_seq
        }
        {
          \seq_map_inline:Nn \g_@@_labelseq_seq
            {
              \str_case:enT
                { \tl_item:nn { ##1 } { 1 } }
                {
                  { mark }    { }
                  { section } { }
                }
                {
                  \int_compare:nNnTF
                    { \tl_item:nn { ##1 } { 2 } }
                    >
                    { \g_@@_note_id_int }
                    { \seq_put_right:Nn \l_@@_tmpb_seq { ##1 } }
                    {
                      \seq_put_right:Ne \l_@@_tmpa_seq
                        { \tl_item:nn { ##1 } { 2 } }
                    }
                }
%    \end{macrocode}
% Also no need for the \texttt{F} branch here, but for a different reason.
% The preprint label plays no role whatsoever if \opt{couteraux=false}, so we
% just drop them altogether if found.
%    \begin{macrocode}
            }
          \seq_gset_eq:NN \g_@@_print_labelseq_queue_seq
            \l_@@_tmpa_seq
          \seq_gset_eq:NN \g_@@_labelseq_seq \l_@@_tmpb_seq
        }
    \group_end:
  }
%    \end{macrocode}
% \end{macro}
%
%
% \cs{@@_check_duplicates:N} provides a general procedure for handling cases
% of multiple passes of content.  Ideally, the job should be done at
% \cs{@@_inhibit_note:F}, if at all possible.  But, failing that, we can rely
% on the fact that the labels of \cs{postnote}s of measuring/trial passes,
% being delayed \cs{write}s (whatsits), don't end up being written to the
% \file{.aux} file.  However, despite this being a general test, and a
% reasonable one, I'd like to restrain it's use to the minimum possible.
% Using this criterion across the board could result in large swings on the
% content of \cs{printpostnotes} and spurious warnings.  Hence, we only apply
% this check for ``eligible'' items.  For signaling this eligibility, the note
% must have been stored with the \cs{l_@@_maybe_multi_bool} set to
% \texttt{true}, which is then saved in the \texttt{multibool} property.  One
% implication of this procedure is that, if there are any new notes marked as
% \texttt{multibool}, three rounds of compilation will be needed, since the
% labels of the printed notes will be written only on the second run and the
% document will thus require a third one to stabilize.
%
% \begin{macro}{\@@_check_duplicates:N}
%   \begin{syntax}
%     \cs{@@_check_duplicates:N} \meta{\cs{g_@@_print_queue_seq}}
%   \end{syntax}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_check_duplicates:N #1
  {
%    \end{macrocode}
% On a first run, don't even try to check for duplicates.  Better
% \texttt{transitorily} let some duplicates pass than to drop every legitimate
% note.
%    \begin{macrocode}
    \bool_lazy_and:nnT
      { ! \g_@@_firstrun_bool }
      { ! \g_@@_counteraux_bool }
      {
        \group_begin:
          \seq_clear:N \l_@@_tmpa_seq
          \seq_map_inline:Nn #1
            {
              \bool_lazy_or:nnTF
                { \cs_if_exist_p:c { \c_@@_ref_prefix_tl @ mark @ ##1 } }
%    \end{macrocode}
% Always keep sections.  Empty sections are discarded anyway, and they are
% unlikely to occur in places performing multiple passes.
%    \begin{macrocode}
                {
                  \str_if_eq_p:ee
                    { \@@_prop_item:nn {##1} { type } } { section }
                }
                { \seq_put_right:Nn \l_@@_tmpa_seq {##1} }
                {
%    \end{macrocode}
% If \texttt{multibool} is true for the note, we drop it silently, otherwise
% we include it, but warn of possible duplicate.
%    \begin{macrocode}
                  \str_if_eq:eeF
                    { \@@_prop_item:nn {##1} { multibool } }
                    { true }
                    {
                      \seq_put_right:Nn \l_@@_tmpa_seq {##1}
                      \bool_if:NT \l_@@_check_dupli_bool
                        {
                          \msg_warning:nne { postnotes } { possible-duplicate }
                            { \@@_prop_item:nn {##1} { mark } }
                        }
                    }
                }
            }
          \seq_gset_eq:NN #1 \l_@@_tmpa_seq
        \group_end:
      }
  }
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
\msg_new:nnn { postnotes } { possible-duplicate }
  { Possible~duplicate~*around*~note~'#1'~\msg_line_context:. }
%    \end{macrocode}
%
%
% \begin{macro}{\@@_check_floats:N}
%   \begin{syntax}
%     \cs{@@_check_floats:N} \meta{\cs{g_@@_print_queue_seq}}
%   \end{syntax}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_check_floats:N #1
  {
    \bool_lazy_and:nnT
      { \l_@@_check_floats_bool }
%    \end{macrocode}
% Ditto.  In this case, the queue is not touched, but it would still be a
% spurious warning.
%    \begin{macrocode}
      { ! \g_@@_firstrun_bool }
      {
        \group_begin:
%    \end{macrocode}
% Only compare sequence net of non-existing labels.
%    \begin{macrocode}
          \seq_set_filter:NNn \l_@@_tmpa_seq #1
            {
              \bool_lazy_or_p:nn
                { \cs_if_exist_p:c { \c_@@_ref_prefix_tl @ mark @ ##1 } }
                { \cs_if_exist_p:c { \c_@@_ref_prefix_tl @ section @ ##1 } }
            }
%    \end{macrocode}
% Not very \texttt{expl3}-y, I know.  But I don't see a \cs{seq_if_eq:NNTF}
% available and, technically, sequences are just structured token lists.
%    \begin{macrocode}
          \tl_if_eq:NNF
            \g_@@_print_labelseq_queue_seq \l_@@_tmpa_seq
            { \msg_warning:nn { postnotes } { possible-shuffle } }
        \group_end:
      }
  }
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
\msg_new:nnn { postnotes } { possible-shuffle }
  { Possible~out~of~sequence~notes~due~to~floats~\msg_line_context:. }
%    \end{macrocode}
%
%
% \begin{macro}{\@@_sort_queue:N}
%   Sorting function for \cs{@@_print_notes:}.
%   \begin{syntax}
%     \cs{@@_sort_queue:N} \meta{\cs{g_@@_print_queue_seq}}
%   \end{syntax}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_sort_queue:N #1
  {
    \bool_if:NT \l_@@_sort_bool
      {
        \group_begin:
          \seq_gsort:Nn #1
            {
              \@@_prop_get:nnN {##1} { pnsectid } \l_@@_tmpa_tl
              \@@_prop_get:nnN {##2} { pnsectid } \l_@@_tmpb_tl
              \tl_if_eq:NNTF \l_@@_tmpa_tl \l_@@_tmpb_tl
                {
                  \@@_prop_get:nnN {##1} { type } \l_@@_tmpa_tl
                  \@@_prop_get:nnN {##2} { type } \l_@@_tmpb_tl
                  \bool_lazy_and:nnTF
                    { \str_if_eq_p:Vn \l_@@_tmpa_tl { note } }
                    { \str_if_eq_p:Vn \l_@@_tmpb_tl { note } }
                    {
                      \@@_prop_get:nnN {##1}
                        { sortnum } \l_@@_tmpa_tl
                      \@@_prop_get:nnN {##2}
                        { sortnum } \l_@@_tmpb_tl
                      \fp_compare:nNnTF
                        { \l_@@_tmpa_tl } > { \l_@@_tmpb_tl }
                        { \sort_return_swapped: }
                        { \sort_return_same:    }
                    }
                    { \sort_return_same: }
                }
                { \sort_return_same: }
            }
        \group_end:
      }
  }
%    \end{macrocode}
% \end{macro}
%
%
%    \begin{macrocode}
\AddToHook { enddocument/afterlastpage }
  {
    \group_begin:
      \bool_if:NTF \g_@@_counteraux_bool
        {
          \seq_set_filter:NNn \l_@@_tmpa_seq \g_@@_labelseq_seq
            { \str_if_eq_p:ee { \tl_item:nn {#1} { 1 } } { mark } }
        }
        {
          \seq_set_filter:NNn \l_@@_tmpa_seq \g_@@_queue_seq
            { \str_if_eq_p:ee { \@@_prop_item:nn {#1} { type } } { note } }
        }
      \seq_if_empty:NF \l_@@_tmpa_seq
        {
          \msg_warning:nne { postnotes } { stray-notes }
            { \seq_count:N \l_@@_tmpa_seq }
        }
    \group_end:
  }
\msg_new:nnn { postnotes } { stray-notes }
  {
    There~are~'#1'~stray~notes~after~the~last~'\iow_char:N\\printpostnotes'~
    \msg_line_context:.~At~this~point,~they~are~lost.
  }
%    \end{macrocode}
%
%
%
% \section{Headers}
%
% The headers infrastructure of \pkg{postnotes} is comprised of three basic
% parts:
%
% \begin{enumerate}
% \item For each \cs{postnote}, labels are set storing the \texttt{page} where
%   the note occurs.  Each note actually generates a pair of such labels, once
%   when \cs{postnote} is called (with the mark), and another where the note
%   is printed (in \cs{printpostnotes}).  The former ones store \cs{thepage},
%   since we want the printed representation of it for typesetting purposes,
%   the latter ones store the value of the \texttt{page} counter, since we
%   don't need to typeset it, but do need to perform algebraic operations with
%   it.  These labels are set by \cs{@@_set_mark_page_label:nn},
%   \cs{@@_set_text_page_label:n}, and \cs{@@_set_print_page_label:n} at the
%   appropriate places.  The set of these labels provides a mapping from each
%   note's ``mark'' and ``text'' to the page where it occurs.
% \item This information set is processed by \cs{@@_get_headers_data:N} at the
%   beginning of \cs{@@_print_notes:} to identify the first and last note of
%   each page in \cs{printpostnotes}, and to generate a mapping from these
%   first and last notes on each page to the pages where their corresponding
%   marks occur.  We also take the opportunity to enrich this mapping with
%   other metadata of each note.  So we get also mappings from the first and
%   last note on each page to \cs{thechapter}, \cs{thesection}, and the
%   \opt{name} of the section in which they occur.  These mappings are stored
%   in property lists \cs[no-index]{g_@@_header_\meta{info}_first_prop} and
%   \cs[no-index]{g_@@_header_\meta{info}_last_prop} where the \texttt{key} is
%   the page in \cs{printpostnotes} where their note's content is typeset (or
%   rather where it starts to be typeset, it is the page where the text's mark
%   is printed).
% \item Based on these mappings, along the span of notes section we run
%   \cs{@@_set_headers_vars_next:} at each \texttt{shipout/before} hook to set
%   user facing variables for the \emph{next} page, which will be available
%   when their heading gets typeset.  Given that at \texttt{shipout} we can
%   rely on a correct value of the \texttt{page} counter, we use it as
%   \texttt{key} to query the property lists generated in the previous step.
%   These user facing variables are called \cs[no-index]{pnhd\meta{info}first}
%   and \cs[no-index]{pnhd\meta{info}last}.  Since we cannot rely on the
%   shipout hook for the first page of \cs{printpostnotes},
%   \cs{@@_set_headers_vars_first:} is run at its beginning to ensure correct
%   values are in place on the first page of the notes section.
% \end{enumerate}
%
% These \cs[no-index]{pnhd\meta{info}first} and
% \cs[no-index]{pnhd\meta{info}last} variables can then be used to build
% simple functions which can be passed to mark commands to achieve rich
% contextual running headers.
%
%
% \begin{macro}[int]
%   {
%     \pnhdpagefirst ,
%     \pnhdpagelast ,
%     \pnhdchapfirst ,
%     \pnhdchaplast ,
%     \pnhdsectfirst ,
%     \pnhdsectlast ,
%     \pnhdnamefirst ,
%     \pnhdnamelast ,
%   }
%   User facing variables, aimed at making available header data for the user.
%   Setting these variables with correct values at the moment the header gets
%   typeset is \emph{the} objective of the whole headers infrastructure of the
%   package.
%    \begin{macrocode}
\tl_new:N \pnhdpagefirst
\tl_new:N \pnhdpagelast
\tl_new:N \pnhdchapfirst
\tl_new:N \pnhdchaplast
\tl_new:N \pnhdsectfirst
\tl_new:N \pnhdsectlast
\tl_new:N \pnhdnamefirst
\tl_new:N \pnhdnamelast
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}
%   {
%     \g_@@_header_page_first_prop ,
%     \g_@@_header_page_last_prop ,
%     \g_@@_header_chap_first_prop ,
%     \g_@@_header_chap_last_prop ,
%     \g_@@_header_sect_first_prop ,
%     \g_@@_header_sect_last_prop ,
%     \g_@@_header_name_first_prop ,
%     \g_@@_header_name_last_prop ,
%     \g_@@_header_prev_last_page_tl ,
%     \g_@@_header_prev_last_chap_tl ,
%     \g_@@_header_prev_last_sect_tl ,
%     \g_@@_header_prev_last_name_tl ,
%     \l_@@_prev_text_page_tl ,
%     \l_@@_curr_text_page_tl ,
%     \l_@@_prev_mark_page_tl ,
%     \l_@@_prev_mark_chap_tl ,
%     \l_@@_prev_mark_sect_tl ,
%     \l_@@_prev_mark_name_tl ,
%   }
%   Auxiliary variables for the headers infrastructure.
%    \begin{macrocode}
\prop_new:N \g_@@_header_page_first_prop
\prop_new:N \g_@@_header_page_last_prop
\prop_new:N \g_@@_header_chap_first_prop
\prop_new:N \g_@@_header_chap_last_prop
\prop_new:N \g_@@_header_sect_first_prop
\prop_new:N \g_@@_header_sect_last_prop
\prop_new:N \g_@@_header_name_first_prop
\prop_new:N \g_@@_header_name_last_prop
\tl_new:N \g_@@_header_prev_last_page_tl
\tl_new:N \g_@@_header_prev_last_chap_tl
\tl_new:N \g_@@_header_prev_last_sect_tl
\tl_new:N \g_@@_header_prev_last_name_tl
\tl_new:N \l_@@_prev_text_page_tl
\tl_new:N \l_@@_curr_text_page_tl
\tl_new:N \l_@@_prev_mark_page_tl
\tl_new:N \l_@@_prev_mark_chap_tl
\tl_new:N \l_@@_prev_mark_sect_tl
\tl_new:N \l_@@_prev_mark_name_tl
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\@@_get_headers_data:N}
%   Process header data for \cs{@@_set_headers_vars:n}.
%   \begin{syntax}
%     \cs{@@_get_headers_data:N} \meta{\cs{g_@@_print_queue_seq}}
%   \end{syntax}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_get_headers_data:N #1
  {
    \group_begin:
      \tl_gclear:N \pnhdpagefirst
      \tl_gclear:N \pnhdpagelast
      \tl_gclear:N \pnhdchapfirst
      \tl_gclear:N \pnhdchaplast
      \tl_gclear:N \pnhdsectfirst
      \tl_gclear:N \pnhdsectlast
      \tl_gclear:N \pnhdnamefirst
      \tl_gclear:N \pnhdnamelast
      \prop_gclear:N \g_@@_header_page_first_prop
      \prop_gclear:N \g_@@_header_page_last_prop
      \prop_gclear:N \g_@@_header_chap_first_prop
      \prop_gclear:N \g_@@_header_chap_last_prop
      \prop_gclear:N \g_@@_header_sect_first_prop
      \prop_gclear:N \g_@@_header_sect_last_prop
      \prop_gclear:N \g_@@_header_name_first_prop
      \prop_gclear:N \g_@@_header_name_last_prop
      \tl_gclear:N \g_@@_header_prev_last_page_tl
      \tl_gclear:N \g_@@_header_prev_last_chap_tl
      \tl_gclear:N \g_@@_header_prev_last_sect_tl
      \tl_gclear:N \g_@@_header_prev_last_name_tl
      \tl_clear:N \l_@@_prev_text_page_tl
      \tl_clear:N \l_@@_curr_text_page_tl
      \tl_clear:N \l_@@_prev_mark_page_tl
      \tl_clear:N \l_@@_prev_mark_chap_tl
      \tl_clear:N \l_@@_prev_mark_sect_tl
      \tl_clear:N \l_@@_prev_mark_name_tl
      \seq_map_inline:Nn #1
        {
          \exp_args:Ne \tl_if_eq:nnT
            { \@@_prop_item:nn {##1} { type } }
            { note }
            {
              \@@_get_pageref:Nn
                \l_@@_curr_text_page_tl { text@ ##1 }
              \tl_if_empty:NF \l_@@_curr_text_page_tl
                {
                  \tl_if_eq:NNTF
                    \l_@@_prev_text_page_tl
                    \l_@@_curr_text_page_tl
                    {
%    \end{macrocode}
% We are on the same page as the previous note, just update the
% \texttt{prev_mark} data.
%    \begin{macrocode}
                      \@@_get_pageref:Nn
                        \l_@@_prev_mark_page_tl { mark@ ##1 }
                      \@@_prop_get:nnN {##1} { thechapter }
                        \l_@@_prev_mark_chap_tl
                      \@@_prop_get:nnN {##1} { thesection }
                        \l_@@_prev_mark_sect_tl
                      \@@_prop_get:nnN {##1} { pnsectname }
                        \l_@@_prev_mark_name_tl
                    }
                    {
%    \end{macrocode}
% We are on the transition between two pages, current ID is the first note of
% the new page (or on the very first note of \cs{printpostnotes}, given
% \cs{l_@@_prev_text_page_tl} is initialized to empty).
%
% Set `last' values for previous page, based on the last valid
% \texttt{prev_mark} stored ones.  There is no previous page to the first one
% of \cs{printpostnotes}, so we don't set `last' values for it (conditioning
% on \cs{l_@@_prev_text_page_tl} being empty, which only occurs on the first
% note).
%    \begin{macrocode}
                      \tl_if_empty:NF \l_@@_prev_text_page_tl
                        {
                          \prop_gput:Nee \g_@@_header_page_last_prop
                            { \l_@@_prev_text_page_tl }
                            { \l_@@_prev_mark_page_tl }
                          \prop_gput:Nee \g_@@_header_chap_last_prop
                            { \l_@@_prev_text_page_tl }
                            { \l_@@_prev_mark_chap_tl }
                          \prop_gput:Nee \g_@@_header_sect_last_prop
                            { \l_@@_prev_text_page_tl }
                            { \l_@@_prev_mark_sect_tl }
                          \prop_gput:Nee \g_@@_header_name_last_prop
                            { \l_@@_prev_text_page_tl }
                            { \l_@@_prev_mark_name_tl }
                        }
%    \end{macrocode}
%
% Set `first' values for current page, based on the current note ID.
%    \begin{macrocode}
                      \prop_gput:Nee \g_@@_header_page_first_prop
                        { \l_@@_curr_text_page_tl }
                        { \@@_extract_pageref:n { mark@ ##1 } }
                      \prop_gput:Nee \g_@@_header_chap_first_prop
                        { \l_@@_curr_text_page_tl }
                        { \@@_prop_item:nn {##1} { thechapter } }
                      \prop_gput:Nee \g_@@_header_sect_first_prop
                        { \l_@@_curr_text_page_tl }
                        { \@@_prop_item:nn {##1} { thesection } }
                      \prop_gput:Nee \g_@@_header_name_first_prop
                        { \l_@@_curr_text_page_tl }
                        { \@@_prop_item:nn {##1} { pnsectname } }
%    \end{macrocode}
%
% Store \texttt{prev_mark} data for the first note on the page.
%    \begin{macrocode}
                      \@@_get_pageref:Nn
                        \l_@@_prev_mark_page_tl { mark@ ##1 }
                      \@@_prop_get:nnN {##1} { thechapter }
                        \l_@@_prev_mark_chap_tl
                      \@@_prop_get:nnN {##1} { thesection }
                        \l_@@_prev_mark_sect_tl
                      \@@_prop_get:nnN {##1} { pnsectname }
                        \l_@@_prev_mark_name_tl
%    \end{macrocode}
%
% Set \cs{l_@@_prev_text_page_tl} for the next page
% (\cs{l_@@_curr_text_page_tl} is never empty at this point, since we
% conditioned to it).
%    \begin{macrocode}
                      \tl_set:NV \l_@@_prev_text_page_tl
                        \l_@@_curr_text_page_tl
                    }
                }
            }
        }
%    \end{macrocode}
% We can't catch the transition from the last page of \cs{printpostnotes} to
% the following one through the mapping above, but the \texttt{prev_mark}
% values of the last note in the loop are the ones we want, so we set `last'
% values for the last page based on them.
%    \begin{macrocode}
      \tl_if_empty:NF \l_@@_prev_text_page_tl
        {
          \prop_gput:Nee \g_@@_header_page_last_prop
            { \l_@@_prev_text_page_tl }
            { \l_@@_prev_mark_page_tl }
          \prop_gput:Nee \g_@@_header_chap_last_prop
            { \l_@@_prev_text_page_tl }
            { \l_@@_prev_mark_chap_tl }
          \prop_gput:Nee \g_@@_header_sect_last_prop
            { \l_@@_prev_text_page_tl }
            { \l_@@_prev_mark_sect_tl }
          \prop_gput:Nee \g_@@_header_name_last_prop
            { \l_@@_prev_text_page_tl }
            { \l_@@_prev_mark_name_tl }
        }
    \group_end:
  }
%    \end{macrocode}
% \end{macro}
%
%
% The sequence of pages processed in \cs{@@_get_headers_data:N} is not ensured
% to be continuous, since not every page of \cs{printpostnotes} starts a note.
% There may be notes that fill whole pages, or the last page of the notes may
% end with a note that started on the penultimate page.  We must handle this
% case at \cs{@@_set_headers_vars:n}.  For every page for which there is
% information provided by \cs{@@_get_headers_data:N} we store a
% \texttt{header_prev_last} (the last value of the previous header) for each
% of the variables of interest.  If the next page is skipped in the sequence
% (no notes starting on it), we can use these stored values to set both
% `first' and `last' variables based on them for that page.
%
%
% \begin{macro}{\@@_set_headers_vars:n}
%   Set user facing variables based on data generated by
%   \cs{@@_get_headers_data:N}.
%   \begin{syntax}
%     \cs{@@_set_headers_vars:n} \Arg{page number}
%   \end{syntax}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_set_headers_vars:n #1
  {
    \group_begin:
      \prop_get:NnNTF \g_@@_header_page_first_prop
        {#1} \l_@@_tmpa_tl
        { \tl_gset:NV \pnhdpagefirst \l_@@_tmpa_tl }
        { \tl_gset:NV \pnhdpagefirst \g_@@_header_prev_last_page_tl }
      \prop_get:NnNTF \g_@@_header_page_last_prop
        {#1} \l_@@_tmpa_tl
        {
          \tl_gset:NV \pnhdpagelast \l_@@_tmpa_tl
          \tl_gset:NV \g_@@_header_prev_last_page_tl
            \l_@@_tmpa_tl
        }
        { \tl_gset:NV \pnhdpagelast \g_@@_header_prev_last_page_tl }
      \prop_get:NnNTF \g_@@_header_chap_first_prop
        {#1} \l_@@_tmpa_tl
        { \tl_gset:NV \pnhdchapfirst \l_@@_tmpa_tl }
        { \tl_gset:NV \pnhdchapfirst \g_@@_header_prev_last_chap_tl }
      \prop_get:NnNTF \g_@@_header_chap_last_prop
        {#1} \l_@@_tmpa_tl
        {
          \tl_gset:NV \pnhdchaplast \l_@@_tmpa_tl
          \tl_gset:NV \g_@@_header_prev_last_chap_tl
            \l_@@_tmpa_tl
        }
        { \tl_gset:NV \pnhdchaplast \g_@@_header_prev_last_chap_tl }
      \prop_get:NnNTF \g_@@_header_sect_first_prop
        {#1} \l_@@_tmpa_tl
        { \tl_gset:NV \pnhdsectfirst \l_@@_tmpa_tl }
        { \tl_gset:NV \pnhdsectfirst \g_@@_header_prev_last_sect_tl }
      \prop_get:NnNTF \g_@@_header_sect_last_prop
        {#1} \l_@@_tmpa_tl
        {
          \tl_gset:NV \pnhdsectlast \l_@@_tmpa_tl
          \tl_gset:NV \g_@@_header_prev_last_sect_tl
            \l_@@_tmpa_tl
        }
        { \tl_gset:NV \pnhdsectlast \g_@@_header_prev_last_sect_tl }
      \prop_get:NnNTF \g_@@_header_name_first_prop
        {#1} \l_@@_tmpa_tl
        { \tl_gset:NV \pnhdnamefirst \l_@@_tmpa_tl }
        { \tl_gset:NV \pnhdnamefirst \g_@@_header_prev_last_name_tl }
      \prop_get:NnNTF \g_@@_header_name_last_prop
        {#1} \l_@@_tmpa_tl
        {
          \tl_gset:NV \pnhdnamelast \l_@@_tmpa_tl
          \tl_gset:NV \g_@@_header_prev_last_name_tl
            \l_@@_tmpa_tl
        }
        { \tl_gset:NV \pnhdnamelast \g_@@_header_prev_last_name_tl }
    \group_end:
  }
\cs_generate_variant:Nn \@@_set_headers_vars:n { e }
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}
%   {
%     \@@_set_headers_vars_next: ,
%     \@@_set_headers_vars_first: ,
%   }
%   The functions that actually call \cs{@@_set_headers_vars:n} at the
%   appropriate contexts with appropriate page values.  Though we set
%   \cs{@@_set_headers_vars_next:} to run at every \texttt{shipout/before}
%   hook of the document, it is made no-op by \cs{g_@@_header_vars_next_bool}
%   which only has a \texttt{true} value inside \cs{printpostnotes}.
%   \cs{@@_set_headers_vars_first:} must set a label and retrieve its value to
%   be able to have a reliable value of its own page.
%    \begin{macrocode}
\AddToHook { shipout/before } [ ./header ]
  { \@@_set_headers_vars_next: }
\bool_new:N \g_@@_header_vars_next_bool
\cs_new_protected:Npn \@@_set_headers_vars_next:
  {
    \bool_if:NT \g_@@_header_vars_next_bool
      { \@@_set_headers_vars:e { \int_eval:n { \c@page + 1 } } }
  }
\cs_new_protected:Npn \@@_set_headers_vars_first:
  {
    \@@_set_print_page_label:e
      { \int_use:N \g_@@_print_postnotes_int }
    \@@_set_headers_vars:e
      {
        \@@_extract_pageref:e
          { print@ \int_use:N \g_@@_print_postnotes_int }
      }
  }
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}[int]{\pnheaderdefault}
%   A basic header function to be used as default in the \opt{heading} option.
%   It produces a header in the form ``Notes to pages N--M'', with a text
%   which can be localized (see Section~\ref{sec:languages}).
%   \begin{syntax}
%     \cs{pnheaderdefault}
%   \end{syntax}
%    \begin{macrocode}
\NewDocumentCommand \pnheaderdefault {}
  {
    \tl_if_eq:NNTF \pnhdpagefirst \pnhdpagelast
      { \pnhdnotes{} ~ \pnhdtopage{} ~ \pnhdpagefirst }
      { \pnhdnotes{} ~ \pnhdtopages{} ~ \pnhdpagefirst -- \pnhdpagelast }
  }
%    \end{macrocode}
% \end{macro}
%
%
% \section{Compatibility}
%
% A dedicated temp variable for restoring data.
%
%    \begin{macrocode}
\tl_new:N \l_@@_restore_tmp_tl
%    \end{macrocode}
%
% \subsection*{\cs{caption}}
%
% For \cs{caption}'s possible two passes.  This catches more than just
% captions, of course, but is not overkill.  A hook to \cs{@makecaption} would
% be better, but \pkg{ltcmdhooks} does not allow it, and using lower level
% methods for this is a bad idea.
%
% From the user's perspective, one-line captions will just work.  For two-line
% captions, there are two alternatives: i)
% \texttt{\textbackslash{}stepcounter\{postnote\}} before the caption, then
% call \cs{postnote} with \texttt{mark=\textbackslash{}arabic\{postnote\}}; or
% ii) right before the caption, call
% \texttt{\textbackslash{}postnote[nomark]\{\textbackslash{}label\{mynote\}...\}},
% then use \texttt{\textbackslash{}postnoteref\{mynote\}} inside the caption.
%
%    \begin{macrocode}
\AddToHook { postnotes/note/begin } [ ./compat/caption ]
  { \cs_if_exist:NT \@captype { \postnotesetup { maybemulti } } }
%    \end{macrocode}
%
%
% \subsection*{\pkg{biblatex}}
%
% Thanks \contributor{Moritz Wemheuer}:
% \url{https://tex.stackexchange.com/q/597359#comment1594585_597389}.
%
%
%    \begin{macrocode}
\AddToHook { package/biblatex/after } [ ./compat/biblatex ]
  {
%    \end{macrocode}
% Let \pkg{biblatex} know we are in a ``notes'' context.  See
% \url{https://tex.stackexchange.com/a/304464}, including comments.
%    \begin{macrocode}
    \AddToHook { postnotes/print/begin } [ postnotes/compat/biblatex ]
      { \toggletrue { blx@footnote } }
%    \end{macrocode}
% Make \pkg{biblatex}'s \cs{mkbibendnote} use \cs{postnote}.  This is very
% likely desired in most cases, but may occasionally not be, so we add it to
% an individually labeled hook, which can be disabled with
% \texttt{\textbackslash{}RemoveFromHook\{begindocument/before\}[postnotes/mkbibendnote]}
% in the preamble.
%    \begin{macrocode}
    \AddToHook { begindocument/before } [ postnotes/compat/biblatex ]
      {
        \cs_set:Npn \blx@theendnote { \postnote }
        \cs_set:Npn \blx@theendnotetext { \blx@err@endnote \footnotetext }
      }
  }
%    \end{macrocode}
%
%
%    \begin{macrocode}
%<*gobble>
%    \end{macrocode}
%
% I had made an initial experimental attempt to support \pkg{biblatex}'s
% \texttt{refsegment}s, \texttt{refcontext}s and \texttt{refsection}s.
% However, this attempt was rash.  Even if I could get many example files to
% work for \texttt{refsegment}s and \texttt{refcontext}s, I could not do so
% for \texttt{refsection}s.  More importantly, with this partial
% implementation, I could also generate documents which confused
% \pkg{biblatex} more than it helped.  Things I couldn't understand well, or
% fix.  All in all, I don't think this partial implementation is tenable, and
% I could not take it further.  Hence, \pkg{postnotes} support for this
% feature set of \pkg{biblatex} will depend, as it should, on proper upstream
% support for ``saving'' and ``restoring'' citation ``context'' information.
%
% I have made a feature request at \pkg{biblatex} for this
% (\url{https://github.com/plk/biblatex/issues/1226}), which was
% (understandably) classified as ``long term, no promises''.
%
%
% The attempt was the following (currently ``gobbled'' from the package):
%
%    \begin{macrocode}
\AddToHook { package/biblatex/after } [ ./compat/biblatex ]
  {
%    \end{macrocode}
% Store \pkg{biblatex} variables for each note.
%    \begin{macrocode}
    \AddToHook { postnotes/note/store } [ postnotes/compat/biblatex ]
      {
        \prop_gput:cne { \@@_data_name:e { \l_postnotes_note_id_tl } }
          { biblatex@refsection } { \int_use:N \c@refsection }
        \prop_gput:cne { \@@_data_name:e { \l_postnotes_note_id_tl } }
          { biblatex@refsegment } { \int_use:N \c@refsegment }
        \prop_gput:cne { \@@_data_name:e { \l_postnotes_note_id_tl } }
          { biblatex@refcontextbool }
          { \iftoggle { blx@refcontext } { true } { false } }
        \prop_gput:cnV { \@@_data_name:e { \l_postnotes_note_id_tl } }
          { biblatex@refcontext } \blx@refcontext@context
      }
%    \end{macrocode}
% \pkg{biblatex} setup, once for \cs{printpostnotes} call.
%    \begin{macrocode}
    \AddToHook { postnotes/print/begin } [ postnotes/compat/biblatex ]
      {
        \@@_biblatex_endrefcontext_local:
        \@@_biblatex_citereset_local:
      }
%    \end{macrocode}
% Restore \pkg{biblatex} variables for each note.
%    \begin{macrocode}
    \AddToHook { postnotes/print/note/begin } [ postnotes/compat/biblatex ]
      {
        \@@_prop_get:nnN { \l_postnotes_print_note_id_tl }
          { biblatex@refsection } \l_@@_restore_tmp_tl
        \int_set:Nn \c@refsection { \l_@@_restore_tmp_tl }
        \@@_prop_get:nnN { \l_postnotes_print_note_id_tl }
          { biblatex@refsegment } \l_@@_restore_tmp_tl
        \int_set:Nn \c@refsegment { \l_@@_restore_tmp_tl }
        \@@_prop_get:nnN { \l_postnotes_print_note_id_tl }
          { biblatex@refcontextbool } \l_@@_restore_tmp_tl
        \use:c { toggle \l_@@_restore_tmp_tl } { blx@refcontext }
        \@@_prop_get:nnN { \l_postnotes_print_note_id_tl }
          { biblatex@refcontext } \l_@@_restore_tmp_tl
        \blx@edef@refcontext { \l_@@_restore_tmp_tl }
      }
%    \end{macrocode}
% Auxiliary functions.
%
% \begin{macro}{\@@_biblatex_endrefcontext_local:}
%   Replicate the job of \cs{endrefcontext}, but with local effects,
%   restrained to the group of \cs{printpostnotes}.
%    \begin{macrocode}
    \cs_new_protected:Npn \@@_biblatex_endrefcontext_local:
      {
        \togglefalse { blx@refcontext }
        \tl_clear:N \blx@refcontext@labelprefix
        \tl_clear:N \blx@refcontext@labelprefix@real
        \tl_set:Ne \blx@refcontext@sortingtemplatename { \blx@sorting }
        \tl_set:Nn \blx@refcontext@sortingnamekeytemplatename { global }
        \tl_set:Nn \blx@refcontext@uniquenametemplatename { global }
        \tl_set:Nn \blx@refcontext@labelalphanametemplatename { global }
        \blx@edef@refcontext
          {
            \blx@refcontext@sortingtemplatename /
            \blx@refcontext@sortingnamekeytemplatename /
            /
            \blx@refcontext@uniquenametemplatename /
            \blx@refcontext@labelalphanametemplatename
          }
      }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_biblatex_citereset_local:}
%   Replicate the job of \cs{citereset}, but with local effects, restrained to
%   the group of \cs{printpostnotes}.
%    \begin{macrocode}
    \cs_new_protected:Npn \@@_biblatex_citereset_local:
      {
%    \end{macrocode}
% \noindent
% {\em\scriptsize\verb|\global\cslet{blx@bsee@\the\c@refsection}\@empty|} \\
% {\em\scriptsize\verb|\global\cslet{blx@fsee@\the\c@refsection}\@empty|}
%    \begin{macrocode}
        \tl_clear:c { blx@bsee@ \int_use:N \c@refsection }
        \tl_clear:c { blx@fsee@ \int_use:N \c@refsection }
%    \end{macrocode}
% {\em\scriptsize\verb|\blx@ibidreset@force|}
%    \begin{macrocode}
        \undef \blx@lastkey@text
        \undef \blx@lastkey@foot
%    \end{macrocode}
% {\em\scriptsize\verb|\blx@idemreset@force|}
%    \begin{macrocode}
        \undef \blx@lasthash@text
        \undef \blx@lasthash@foot
%    \end{macrocode}
% {\em\scriptsize\verb|\blx@opcitreset@force|}
%    \begin{macrocode}
        \clist_map_inline:Nn \blx@trackhash@text
          { \csundef { blx@lastkey@text@ ##1 } }
        \tl_clear:N \blx@trackhash@text
        \clist_map_inline:Nn \blx@trackhash@foot
          { \csundef { blx@lastkey@foot@ ##1 } }
        \tl_clear:N \blx@trackhash@foot
%    \end{macrocode}
% {\em\scriptsize\verb|\blx@loccitreset@force|}
%    \begin{macrocode}
        \clist_map_inline:Nn \blx@trackkeys@text
          { \csundef { blx@lastnote@text@ ##1 } }
        \tl_clear:N \blx@trackkeys@text
        \clist_map_inline:Nn \blx@trackkeys@foot
          { \csundef { blx@lastnote@foot@ ##1 } }
        \tl_clear:N \blx@trackkeys@foot
%    \end{macrocode}
% {\em\scriptsize{}and all of them do:}
%    \begin{macrocode}
        \cs_set_eq:NN \blx@lastmpfn \z@
      }
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
  }
%    \end{macrocode}
%
% \pkg{biblatex}'s \texttt{refsections}, contrary to \texttt{refsegment}s and
% \texttt{refcontext}s which are handled in the \LaTeX{} side of things (as
% far as I can tell), need to go through \texttt{biber}, and must have correct
% corresponding citation data written to the \file{.bcf} file.  And the way
% \cs{refsection} is implemented presumes each section is only ever begun once
% (fair\dots{}), thus making it difficult to ``reopen'' it, or append new
% citations to it later on, when the notes are printed.  The start of a
% \texttt{refsection} must be registered on the \file{.bcf} file, and this is
% done by \cs{refsection} (and its auxiliary functions).  However, a number of
% its characteristics make things particularly difficult for the purpose at
% hand: i) it unconditionally sets a label for the section which, of course,
% cannot be done twice; and, critically, ii) the optional argument of the
% environment (which receives the \meta{resources}) is used to set a local
% assignment to \cs{blx@bibfiles}, based on which the relevant information is
% written to the \file{.bcf} file, and when the group closes the information
% is gone.  My best attempt is below but it is not good.  It feels a wrong
% approach to ``go around'' the intended use of \cs{refsection} so much, and
% it can't handle at all its optional argument, for the reasons above.  It's
% also incomplete, since it does not handle restoring
% \cs{l_@@_biblatex_orig_refsection_tl}.
%
%    \begin{macrocode}
\AddToHook { package/biblatex/after } [ ./compat/biblatex ]
  {
    \tl_new:N \l_@@_biblatex_orig_refsection_tl
    \tl_new:N \g_@@_biblatex_prev_refsection_tl
    \AddToHook { postnotes/print/begin } [ postnotes/compat/biblatex ]
      {
        \tl_set:Ne \l_@@_biblatex_orig_refsection_tl
          { \int_use:N \c@refsection }
        \tl_gset:Ne \g_@@_biblatex_prev_refsection_tl
          { \l_@@_biblatex_orig_refsection_tl }
     }
    \AddToHook { postnotes/print/note/begin } [ postnotes/compat/biblatex ]
      {
        \@@_prop_get:nnN { \l_postnotes_print_note_id_tl }
          { biblatex@refsection } \l_@@_restore_tmp_tl
        \tl_if_eq:NNF
          \l_@@_restore_tmp_tl
          \g_@@_biblatex_prev_refsection_tl
          {
            \int_set:Nn \c@blx@maxsection
              { \l_@@_restore_tmp_tl - 1 }
            \tl_gset_eq:NN \g_@@_biblatex_prev_refsection_tl
              \l_@@_restore_tmp_tl
            \group_begin:
              \cs_set_eq:NN \label \use_none:n
              \cs_set_eq:NN \blx@info \use_none:n
              \blx@endrefsection
              \refsection
            \group_end:
          }
      }
  }
%    \end{macrocode}
%
%    \begin{macrocode}
%</gobble>
%    \end{macrocode}
%
%
% \subsection*{\pkg{zref-user}}
%
% \begin{macro}{\l_@@_note_zlabel_str}
%   Even though the \opt{zlabel} option is provided only when \pkg{zref-user}
%   is loaded, \cs{l_@@_note_zlabel_str} must be unconditionally defined,
%   since it is presumed to exist by \cs{@@_set_user_labels:} and elsewhere.
%    \begin{macrocode}
\str_new:N \l_@@_note_zlabel_str
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
\AddToHook { package/zref-user/after } [ ./compat/zref-user ]
  {
%    \end{macrocode}
% Provide \opt{zlabel} option.
%    \begin{macrocode}
    \keys_define:nn { postnotes/note }
      {
        zlabel .str_set:N = \l_@@_note_zlabel_str ,
        zlabel .value_required:n = true ,
      }
%    \end{macrocode}
% Provide property to store the mark for measuring passes.
%    \begin{macrocode}
    \zref@newprop { postnote@mark } [] { \l_@@_mark_tl }
    \AddToHook { postnotes/note/begin }  [ postnotes/compat/zref-user ]
      { \zref@localaddprop { main } { postnote@mark } }
%    \end{macrocode}
%
% \begin{macro}[int]{\postnotezref}
%   Provide \cs{postnotezref}.
%   \begin{syntax}
%     \cs{postnotezref}\meta{*}\marg{label}
%   \end{syntax}
%    \begin{macrocode}
    \NewDocumentCommand \postnotezref { s m }
      { \@@_note_zref:nn {#1} {#2} }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_note_zref:nn}
%   The internal version of \cs{postnotezref}.
%   \begin{syntax}
%     \cs{@@_note_zref:nn} \Arg{star bool} \Arg{label}
%   \end{syntax}
%    \begin{macrocode}
    \tl_new:N \l_@@_note_zref_zlabel_tl
    \cs_new_protected:Npn \@@_note_zref:nn #1#2
      {
        \group_begin:
          \tl_set:Nn \l_@@_note_zref_zlabel_tl {#2}
          \@@_typeset_mark_wrapper:nnn
            {
              \bool_lazy_all:nTF
                {
                  { ! #1 }
                  { \l_@@_hyperlink_bool }
                  { \l_@@_zrefhyperref_bool }
                }
                {
                  \hyperlink
                    { \zref@extractdefault {#2} { anchor } { } }
                    { \@@_make_mark:nnn { \zref{#2} } { } { } }
                }
                { \@@_make_mark:nnn { \zref{#2} } { } { } }
            }
            { \tag_socket_use:n { postnotes/postnotezref/begin } }
            { \tag_socket_use:n { postnotes/postnotezref/end }   }
        \group_end:
      }
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\bool_new:N \l_@@_zrefhyperref_bool
\AddToHook { package/zref-hyperref/after } [ ./compat/zref-hyperref ]
  { \bool_set_true:N \l_@@_zrefhyperref_bool }
%    \end{macrocode}
%
%
% \subsection*{\pkg{zref-clever}}
%
%    \begin{macrocode}
\AddToHook { package/zref-clever/after } [ ./compat/zref-clever ]
  {
    \zcsetup
      {
        countertype = { postnote = endnote } ,
        countertype = { postnotetext = endnote } ,
      }
    \AddToHook { postnotes/print/begin } [ postnotes/compat/zref-clever ]
      { \zcsetup { counterresetby = { postnotetext = postnotesection } } }
  }
%    \end{macrocode}
%
%
% \subsection*{\pkg{zref-check}}
%
%    \begin{macrocode}
\AddToHook { package/zref-check/after } [ ./compat/zref-check ]
  {
    \IfPackageAtLeastTF { zref-check } { 2022-07-05 }
      {
        \AddToHook { postnotes/note/store } [ postnotes/compat/zref-check ]
          {
            \prop_gput:cne { \@@_data_name:e { \l_postnotes_note_id_tl } }
              { zref-check@abschap } { \int_use:N \c@zc@abschap }
            \prop_gput:cne { \@@_data_name:e { \l_postnotes_note_id_tl } }
              { zref-check@abssec } { \int_use:N \c@zc@abssec }
          }
        \AddToHook { postnotes/print/note/begin } [ postnotes/compat/zref-check ]
          {
            \@@_prop_get:nnN { \l_postnotes_print_note_id_tl }
              { zref-check@abschap } \l_@@_restore_tmp_tl
            \int_set:Nn \c@zc@abschap { \l_@@_restore_tmp_tl }
            \@@_prop_get:nnN { \l_postnotes_print_note_id_tl }
              { zref-check@abssec } \l_@@_restore_tmp_tl
            \int_set:Nn \c@zc@abssec { \l_@@_restore_tmp_tl }
          }
      }
      { }
  }
%    \end{macrocode}
%
%
% \subsection*{\pkg{amsmath}}
%
%    \begin{macrocode}
\AddToHook { package/amsmath/after } [ ./compat/amsmath ]
  {
%    \end{macrocode}
% Testing for \cs{ifmeasuring@} is sufficient to get things right for the
% measuring passes in math environments.
%    \begin{macrocode}
    \AddToHook { postnotes/note/inhibit } [ postnotes/compat/amsmath ]
      {
        \legacy_if:nT { measuring@ }
          {
            \bool_set_true:N \l_@@_inhibit_note_bool
            \bool_set_true:N \l_@@_print_plain_mark_bool
            \bool_set_true:N \l_@@_print_plain_mark_stepcounter_bool
          }
      }
%    \end{macrocode}
% However, the \cs{text} macro, defined by \pkg{amstext} (required by
% \pkg{amsmath}), poses problems if its own.  Despite my best efforts, I could
% not salvage things from the use of \cs{mathchoice} and the redefinitions of
% \cs{setcounter} and \cs{addtocounter} performed by \pkg{amstext}.  Setting
% \opt{maybemulti} when \texttt{firstchoice@} is \texttt{false} grants us a
% working situation for display style.  But the use of \cs{postnote} inside
% \cs{text} (and, if \pkg{amsmath} is loaded, \cs{textnormal}, \cs{textup},
% etc.) in inline math environments is not supported.  If a note really needs
% to be there, one can use the \opt{nomark} option and \cs{postnoteref}.
% Things should work in text mode and in display style.  For some related
% discussion with regard to footnotes, see
% \url{https://tex.stackexchange.com/a/82820} and, in particular, Barbara
% Beeton's comment: ``This is certainly bravura code.  I do hope it doesn't
% result in a request to add \cs{footnote} capabilities to \pkg{amsmath}'s
% multi-line display facilities.  (The answer will almost certainly be "no".
% We agree with Kopka \& Daly.)''
%    \begin{macrocode}
    \AddToHook { postnotes/note/begin } [ postnotes/compat/amsmath ]
      { \legacy_if:nF { firstchoice@ } { \postnotesetup { maybemulti } } }
  }
%    \end{macrocode}
%
%
% \subsection*{\pkg{csquotes}}
%
%    \begin{macrocode}
\AddToHook { package/csquotes/after } [ ./compat/csquotes ]
  {
    \bool_new:N \l_@@_csquotes_measuring_bool
    \BlockquoteDisable
      { \bool_set_true:N \l_@@_csquotes_measuring_bool }
    \AddToHook { postnotes/note/inhibit } [ postnotes/compat/csquotes ]
      {
        \bool_if:NT \l_@@_csquotes_measuring_bool
          {
            \bool_set_true:N \l_@@_inhibit_note_bool
            \bool_set_true:N \l_@@_print_plain_mark_bool
            \bool_set_true:N \l_@@_print_plain_mark_stepcounter_bool
          }
      }
  }
%    \end{macrocode}
%
%
% \subsection*{\pkg{tabularx}}
%
% For the identification of the trial passes in \pkg{tabularx}, see
% \url{https://tex.stackexchange.com/a/640035} (including discussion in the
% comments, thanks \contributor{David Carlisle}), and also
% \url{https://tex.stackexchange.com/a/227155} and
% \url{https://tex.stackexchange.com/a/352134}.
%
%    \begin{macrocode}
\AddToHook { package/tabularx/after } [ ./compat/tabularx ]
  {
    \bool_new:N \l_@@_tabularx_inside_env_bool
    \AddToHook { env/tabularx/begin } [ postnotes/compat/tabularx ]
      {
        \bool_set_true:N \l_@@_tabularx_inside_env_bool
        \cs_set_eq:NN \@@_tabularx_saved_write:Nn \write
      }
    \AddToHook { postnotes/note/inhibit } [ postnotes/compat/tabularx ]
      {
        \bool_lazy_and:nnT
          { \l_@@_tabularx_inside_env_bool }
          { ! \cs_if_eq_p:NN \write \@@_tabularx_saved_write:Nn }
          {
            \bool_set_true:N \l_@@_inhibit_note_bool
            \bool_set_true:N \l_@@_print_plain_mark_bool
            \bool_set_true:N \l_@@_print_plain_mark_stepcounter_bool
          }
      }
    \AddToHook { package/xltabular/after } [ postnotes/compat/xltabular ]
      {
        \AddToHook { env/xltabular/begin } [ postnotes/compat/xltabular ]
          {
            \bool_set_true:N \l_@@_tabularx_inside_env_bool
            \cs_set_eq:NN \@@_tabularx_saved_write:Nn \write
          }
      }
  }
%    \end{macrocode}
%
%
% \subsection*{\pkg{tabularray}}
%
%    \begin{macrocode}
\AddToHook { package/tabularray/after } [ ./compat/tabularray ]
  {
%    \end{macrocode}
% Since version \texttt{2023A}, from 2023-03-01, \pkg{tabularray} offers the
% \cs{lTblrMeasuringBool} which is true when measuring and false otherwise.
% See \url{https://tex.stackexchange.com/q/675818}
% and \url{https://github.com/lvjr/tabularray/issues/179} (thanks
% \contributor{Ulrike Fischer}).
%    \begin{macrocode}
    \bool_if_exist:NT \lTblrMeasuringBool
      {
%    \end{macrocode}
% I'd be inclined to restrict the inhibition effect to known \pkg{tabularray}
% environments to ``keep things under control''.  However this is a dedicated
% and public boolean, and users can create arbitrary new \pkg{tabularray}
% environments with \cs{NewTblrEnviron}, which we either wouldn't catch or
% have to provide an user interface for.  So, for the time being, let's trust
% this boolean won't be misused by third-parties or users.  Note that setting
% \cs{l_@@_print_plain_mark_stepcounter_bool} to true presumes
% \pkg{tabularray}'s \texttt{counter} module is enabled.  But, since this is
% the only way to get the measuring right in this context if there is more
% than one \cs{postnote} inside a given table, \pkg{postnotes} expects and
% requires the \texttt{counter} module.
%    \begin{macrocode}
        \AddToHook { postnotes/note/inhibit } [ postnotes/compat/tabularray ]
          {
            \bool_if:NT \lTblrMeasuringBool
              {
                \bool_set_true:N \l_@@_inhibit_note_bool
                \bool_set_true:N \l_@@_print_plain_mark_bool
                \bool_set_true:N \l_@@_print_plain_mark_stepcounter_bool
              }
          }
      }
  }
%    \end{macrocode}
%
%
% \subsection*{PDF Tagging (experimental)}
%
% Note: All of this mostly presumes
% \texttt{\cs{DocumentMetadata}\{testphase=phase-III\}} and was tested with
% it.  For \opt{listenv=none}, I'd expect things to work with
% \texttt{phase-II}, but this is only lightly tested.
%
% A first thing to consider in tagging endnotes is how we want to represent
% them in the PDF structure.  My first thought, for lack of another, was:
% emulate footnotes.  There's no relevant semantic difference at the structure
% level between the two, and the tagging support for footnotes was done by the
% pros.  And one distinctive characteristic the the footnotes tagging is that
% the footnote itself is placed in the structure as a child to the (parent)
% \texttt{text} element which surrounds the footnote mark.  However, for
% endnotes this introduces a number of problems and complicates things.  While
% footnotes ``float around'' and have no real structure of their own, that is
% not true for endnotes.  Endnotes comprise a proper document section, and may
% be printed in a list environment, etc.  So when the tagging of footnotes
% places the footnote structure element as a child element of the mark's
% surrounding text, this is arguably for a lack of other options.  Where else,
% after all?  Indeed, a typical \texttt{html} would render footnotes at the
% end of the page, and not inline.  True the normal \texttt{html} page is much
% smaller than our typical PDF, but the point stands.  We can have a hover
% over call out for footnotes, but the same could be done for end notes,
% regardless of the parent-child relation (as long as the required
% cross-references are in place).  On the other hand, for endnotes this is not
% an issue: they have a natural place to be plugged into.  Furthermore, making
% an endnote a child of the text surrounding its mark leaves an empty
% ``skeleton'' of the endnotes section: the heading, the list structure, etc.
% Technically, we could clean that too, but clearly that's not the way to
% go\dots{}.
%
% Finally, the parent-child relation is not required by \texttt{PDF} standards
% for the relevant structure types.  The \texttt{PDF} 2.0 standard
% (ISO~32000-2:2020), says the following about \texttt{FENote}:
%
% \begin{quote}
%   Used to markup footnotes and endnotes.  Footnotes and endnotes are content
%   that is not normally read as part of the enclosing content from which it
%   is referenced, but rather consulted at the reading person's discretion.
%   In order for text to be considered a footnote or endnote, there should be
%   a reference from the enclosing content to the footnote or endnote.  Such
%   reference may be achieved by means of a Link structure element through a
%   structure destination in its link annotation (see ``Table 368 — General
%   inline level structure types''), or use of Ref in structure elements (see
%   ``Table 355 — Entries in a structure element dictionary'').
% \end{quote}
%
% The \texttt{PDF} 1.7 standard (PDF~32000-1:2008), says the following about
% \texttt{Note}:
%
% \begin{quote}
%   An item of explanatory text, such as a footnote or an endnote, that is
%   referred to from within the body of the document.  It may have a label
%   (structure type Lbl; see ``List Elements'' in 14.8.4.3, ``Block-Level
%   Structure Elements'') as a child.  The note may be included as a child of
%   the structure element in the body text that refers to it, or it may be
%   included elsewhere (such as in an endnotes section) and accessed by means
%   of a reference (structure type Reference).
%
%   Tagged PDF does not prescribe the placement of footnotes in the page
%   content order.  They may be either inline or at the end of the page, at
%   the discretion of the conforming writer.
% \end{quote}
%
% So, the note \emph{may} be included as a child of the surrounding text, but
% that's not required (PDF 2.0 does not even mention that).  What is required
% is the reference between the elements.  All in all, let's not follow
% footnotes in establishing the parent-child relation.
%
%
% Another smaller but related issue is how to treat the list structure in
% \cs{printpostnotes} when \opt{listenv} is used.  The natural thing here
% would be to use an \env{enumerate} type list (or, in PDF lingo, for the
% \texttt{ListNumbering} attribute to be \texttt{Ordered}), where the mark is
% used as the item's label (even if, technically, we use the list like a
% \env{description} in that we feed the label of every \cs{item} and though
% there is an implicit underlying counter, the list itself has no bearing upon
% it).  The problem here is that the PDF 2.0 standards determine that the
% \texttt{FENote} structure element cannot be a child of a \texttt{LI} (list
% item).  However, at least in principle, we also would like to have the
% \texttt{endnotelabel} element to be a child of the \texttt{endnote} element.
% Thus, we have a conflict, the mc-chunk can only be used once, and can be
% either the \texttt{Lbl} of the \texttt{LI}, or the \texttt{endnotelabel} for
% the \texttt{endnote}.  Currently, for the list case, I'm using an
% \texttt{EndnotesList} class, which we define to have \texttt{ListNumbering}
% as \texttt{Ordered}, with the mark as \texttt{Lbl} for \texttt{LI}, and
% letting \texttt{endnote} be a child of \texttt{LBody}.  In a way, the
% possibility of exporting the tagged content to different formats makes me
% think that this is the most appropriate for the this case.  For the case of
% \texttt{listenv=none}, the \texttt{endnote}s were made child of the
% \texttt{Sect} in which they occur.  The \texttt{endnotelabel} was then
% included as part (child) of the \texttt{endnote}.  In this, this treatment
% emulates the one given for footnotes in the kernel.  But, at the same time,
% it is less than ideal for machine readability purposes, since whether the
% \texttt{endnotelabel} is part of \texttt{endnote} or not depends on if there
% is a list environment involved.  Alas, I see no easy way around the PDF
% standard restriction for the list case.
%
%
% On the \LaTeX{} side of things, adding support for tagging entails two basic
% tasks: i) applying the tagging markup at the appropriate places; ii)
% generating references between the ``mark(s)'' and the ``text'' (plus
% cross-reference commands to their respective targets).
%
% Regarding tagging references, we have three different cases: i) a regular
% \cs{postnote}; ii) a \cs{postnoteref} to a note labeled from inside the
% note; and iii) a \cs{postnoteref} to a note labeled with the \opt{label}
% option.
%
% For regular \cs{postnote}s it is trivial to establish the reference using
% the \texttt{label} / \texttt{ref} options of \pkg{tagpdf}.
%
% For \cs{postnoteref}s, however labeled, the connection \emph{must} be
% established at \cs{postnoteref}, for the simple fact that any \cs{postnote}
% can be referenced by arbitrarily many \cs{postnoteref}s.  So we need to be
% able to retrieve the note ID from the ``text'' to which the reference refers
% to at \cs{postnoteref}.  However, at \cs{postnoteref} the only information we
% have is the \meta{label} but, since it is unique, we can establish a
% connection through it.
%
% When the label is set from inside the note, it is actually set at
% \cs{printpostnotes}, at which place we have access to
% \cs{l_postnotes_print_note_id_tl} so we can use the \meta{label} to pass
% that information around to \cs{postnoteref}.  With a standard \cs{label} we
% must set an additional \pkg{ltproperties} label, using the new
% \texttt{label} hook, which \cs{postnoteref} can retrieve from its own
% \meta{label} argument.  For \cs{zlabel} this particular task is trivial,
% since we can simply add a property to store the note ID with the label,
% which \cs{postnotezref} can extract.
%
% When the label is set from the option, things are slightly more complicated,
% because the label is set at \cs{postnote}, at which place we do not have
% access to the note ID of the ``text''.  What we do here is then store the
% label with the note and restore it later at \cs{printpostnotes} as usual.
% Then, at that point, we can set an auxiliary label which can be retrieved
% from \cs{postnoteref} from its own \meta{label} argument, as we did for the
% case of labels inside the note.  Auxiliary labels are handled with
% \pkg{ltproperties} labels.
%
%
% Unconditionally define tagging support sockets.
%    \begin{macrocode}
\socket_new:nn { tagsupport/postnotes/mark/begin }{ 0 }
\socket_new:nn { tagsupport/postnotes/mark/end }{ 0 }
\socket_new:nn { tagsupport/postnotes/nomark/begin }{ 0 }
\socket_new:nn { tagsupport/postnotes/nomark/end }{ 0 }
\socket_new:nn { tagsupport/postnotes/multisep/begin }{ 0 }
\socket_new:nn { tagsupport/postnotes/multisep/end }{ 0 }
\socket_new:nn { tagsupport/postnotes/printlist/begin }{ 0 }
\socket_new:nn { tagsupport/postnotes/printlist/end }{ 0 }
\socket_new:nn { tagsupport/postnotes/printnote/begin }{ 0 }
\socket_new:nn { tagsupport/postnotes/printnote/end }{ 0 }
\socket_new:nn { tagsupport/postnotes/printmark/begin }{ 0 }
\socket_new:nn { tagsupport/postnotes/printmark/end }{ 0 }
\socket_new:nn { tagsupport/postnotes/printtext/begin }{ 0 }
\socket_new:nn { tagsupport/postnotes/printtext/end }{ 0 }
\socket_new:nn { tagsupport/postnotes/postnoteref/begin }{ 0 }
\socket_new:nn { tagsupport/postnotes/postnoteref/end }{ 0 }
\socket_new:nn { tagsupport/postnotes/postnotezref/begin }{ 0 }
\socket_new:nn { tagsupport/postnotes/postnotezref/end }{ 0 }
%    \end{macrocode}
%
%    \begin{macrocode}
\bool_lazy_and:nnT
  { \cs_if_exist_p:N \tag_if_active_p: }
  { \tag_if_active_p: }
  {
%    \end{macrocode}
% FIXME Review or remove these settings if/when they are included upstream
% (see \url{https://github.com/latex3/tagging-project/issues/728}).
%    \begin{macrocode}
    \tagpdfsetup
      {
        role/new-tag = { tag=endnote, role=FENote } ,
        role/new-tag = { tag=endnotemark, role=Lbl } ,
        role/new-tag = { tag=endnotelabel, role=Lbl } ,
        role/new-attribute =
          { EndnoteType } { /O /FENote /NoteType /Endnote } ,
        role/new-attribute =
          { EndnotesList } { /O /List /ListNumbering /Ordered } ,
      }
%    \end{macrocode}
% \cs{postnote}
%    \begin{macrocode}
    \socket_new_plug:nnn { tagsupport/postnotes/mark/begin } { default }
      {
        \tag_mc_end_push:
        \tag_struct_begin:n
          {
            tag = endnotemark ,
            label = { postnotemark. \l_postnotes_note_id_tl } ,
            ref = { postnote. \l_postnotes_note_id_tl } ,
          }
        \@@_tagsup_store_sctructnum:nN
          { postnotemark } \l_postnotes_note_id_tl
        \tag_mc_begin:n { }
      }
    \socket_new_plug:nnn { tagsupport/postnotes/mark/end } { default }
      {
        \tag_mc_end:
        \tag_struct_end: % endnotemark
        \tag_mc_begin_pop:n { }
      }
    \socket_new_plug:nnn { tagsupport/postnotes/nomark/begin } { default }
      {
        \tag_struct_begin:n
          {
            tag = NonStruct ,
            label = { postnotemark. \l_postnotes_note_id_tl } ,
            ref = { postnote. \l_postnotes_note_id_tl } ,
          }
        \@@_tagsup_store_sctructnum:nN
          { postnotemark } \l_postnotes_note_id_tl
      }
    \socket_new_plug:nnn { tagsupport/postnotes/nomark/end } { default }
      { \tag_struct_end: } % NonStruct
    \socket_assign_plug:nn { tagsupport/postnotes/mark/begin } { default }
    \socket_assign_plug:nn { tagsupport/postnotes/mark/end } { default }
    \socket_assign_plug:nn { tagsupport/postnotes/nomark/begin } { default }
    \socket_assign_plug:nn { tagsupport/postnotes/nomark/end } { default }
%    \end{macrocode}
% \opt{multiple}
%    \begin{macrocode}
    \socket_new_plug:nnn { tagsupport/postnotes/multisep/begin } { default }
      {
        \tag_mc_end_push:
        \tag_mc_begin:n { artifact }
      }
    \socket_new_plug:nnn { tagsupport/postnotes/multisep/end } { default }
      {
        \tag_mc_end:
        \tag_mc_begin_pop:n { }
      }
    \socket_assign_plug:nn { tagsupport/postnotes/multisep/begin } { default }
    \socket_assign_plug:nn { tagsupport/postnotes/multisep/end } { default }
%    \end{macrocode}
% \cs{printpostnotes}
%    \begin{macrocode}
    \socket_new_plug:nnn { tagsupport/postnotes/printlist/begin } { default }
      { \tag_tool:n { para/tagging=false } }
    \socket_new_plug:nnn { tagsupport/postnotes/printlist/end } { default }
      { }
    \socket_assign_plug:nn { tagsupport/postnotes/printlist/begin } { default }
    \socket_assign_plug:nn { tagsupport/postnotes/printlist/end } { default }
    \socket_new_plug:nnn { tagsupport/postnotes/printnote/begin } { default }
      {
        \bool_if:NF \l_@@_print_as_list_bool
          {
            \tag_struct_begin:n
              {
                tag = endnote ,
                attribute-class = EndnoteType ,
                label = { postnote. \l_postnotes_print_note_id_tl } ,
%    \end{macrocode}
% CHECK Should we really add a back reference here?  I couldn't find any hint
% about this in the standards, but \pkg{latex-lab-footnotes} does it.  No
% harm, I guess.
%    \begin{macrocode}
                ref = { postnotemark. \l_postnotes_print_note_id_tl } ,
              }
            \@@_tagsup_store_sctructnum:nN
              { postnote } \l_postnotes_print_note_id_tl
         }
      }
    \socket_new_plug:nnn { tagsupport/postnotes/printnote/end } { default }
      {
        \bool_if:NF \l_@@_print_as_list_bool
          { \tag_struct_end: }  % endnote
      }
    \socket_assign_plug:nn { tagsupport/postnotes/printnote/begin } { default }
    \socket_assign_plug:nn { tagsupport/postnotes/printnote/end } { default }
    \socket_new_plug:nnn { tagsupport/postnotes/printmark/begin } { default }
      {
        \bool_if:NF \l_@@_print_as_list_bool
          {
            \tag_struct_begin:n { tag=endnotelabel }
            \tag_mc_begin:n { tag=Lbl }
          }
      }
    \socket_new_plug:nnn { tagsupport/postnotes/printmark/end } { default }
      {
        \bool_if:NF \l_@@_print_as_list_bool
          {
            \tag_mc_end:
            \tag_struct_end: % endnotelabel
          }
      }
    \socket_assign_plug:nn { tagsupport/postnotes/printmark/begin } { default }
    \socket_assign_plug:nn { tagsupport/postnotes/printmark/end } { default }
    \socket_new_plug:nnn { tagsupport/postnotes/printtext/begin } { default }
      {
        \bool_if:NTF \l_@@_print_as_list_bool
          {
            \tag_struct_begin:n
              {
                tag = endnote ,
                attribute-class = EndnoteType ,
                label = { postnote. \l_postnotes_print_note_id_tl } ,
%    \end{macrocode}
% CHECK Ditto.
%    \begin{macrocode}
                ref = { postnotemark. \l_postnotes_print_note_id_tl } ,
              }
            \@@_tagsup_store_sctructnum:nN
              { postnote } \l_postnotes_print_note_id_tl
            \tag_struct_begin:n { tag=text-unit }
            \tag_struct_begin:n { tag=text }
            \tag_tool:n { para/tagging=true }
            \tag_mc_begin:n { }
          }
          {
            \tag_struct_begin:n { tag=text-unit }
            \tag_struct_begin:n { tag=text }
            \tag_tool:n { para/tagging=true }
            \tag_mc_begin:n { }
          }
      }
    \socket_new_plug:nnn { tagsupport/postnotes/printtext/end } { default }
      {
        \bool_if:NTF \l_@@_print_as_list_bool
          {
            \tag_mc_end:
            \tag_tool:n { para/tagging=false }
            \tag_struct_end: % text
            \tag_struct_end: % text-unit
            \tag_struct_end: % endnote
          }
          {
            \tag_mc_end:
            \tag_tool:n { para/tagging=false }
            \tag_struct_end: % text
            \tag_struct_end: % text-unit
          }
      }
    \socket_assign_plug:nn { tagsupport/postnotes/printtext/begin } { default }
    \socket_assign_plug:nn { tagsupport/postnotes/printtext/end } { default }
%    \end{macrocode}
% Provide \pkg{xtemplate} based redefinitions of \env{postnoteslist} and
% \pkg{postnoteslisthang}.  This is needed because, as far as I can tell, it
% is the only way to set \opt{tag} and \opt{attribute-class} for the list
% struct without tampering with \pkg{latex-lab-testphase-block}'s internals.
%    \begin{macrocode}
    \IfInstanceExistsT { blockenv } { list }
      {
        \DeclareInstance { blockenv } { postnoteslist } { display }
          {
            env-name       = postnoteslist ,
            tag-name       = L ,
            tag-class      = EndnotesList ,
            tagging-recipe = list ,
            inner-level-counter = ,
            level-increase = true ,
            setup-code     = ,
            block-instance = list ,
            inner-instance = postnoteslist ,
          }
        \DeclareInstanceCopy { blockenv }
          { postnoteslisthang } { postnoteslist }
        \EditInstance { blockenv } { postnoteslisthang }
          { env-name = postnoteslisthang }
        \DeclareInstance { list } { postnoteslist } { std }
          { item-instance = postnoteslist }
        \DeclareInstance { item } { postnoteslist } { std }
          {
            label-format = { \hspace { \labelsep } \normalfont ~ #1 } ,
            label-align = left ,
          }
        \RenewDocumentEnvironment { postnoteslist } { }
          {
            \UseInstance { blockenv } { postnoteslist }
              {
                leftmargin     = 0pt ,
                label-width    = 0pt ,
                item-indent    = .5\parindent ,
                rightmargin    = 0pt ,
                parindent      = \parindent ,
                par-skip       = \parskip ,
                item-skip      = 0pt ,
                beginsep       = .5\topsep ,
                begin-par-skip = .5\partopsep ,
              }
          }
          { \endblockenv }
        \RenewDocumentEnvironment { postnoteslisthang } { }
          {
            \UseInstance { blockenv } { postnoteslisthang }
              {
                leftmargin     = 1em ,
                label-width    = -\leftmargin ,
                item-indent    = -2\leftmargin ,
                rightmargin    = 0pt ,
                parindent      = \parindent ,
                par-skip       = \parskip ,
                item-skip      = 0pt ,
                beginsep       = .5\topsep ,
                begin-par-skip = .5\partopsep ,
              }
          }
          { \endblockenv }
      }
%    \end{macrocode}
% Setup for \cs{label} and \cs{zlabel} inside the note.
%    \begin{macrocode}
    \bool_new:N \l_@@_inside_note_bool
    \AddToHookWithArguments { label } [ postnotes/tagsup ]
      {
        \bool_if:NT \l_@@_inside_note_bool
          {
            \property_record:nn { postnote@label@innote. #1 }
              { postnotes/tagsup@noteid }
          }
      }
    \AddToHook { postnotes/print/note/begin } [ postnotes/tagsup ]
      { \bool_set_true:N \l_@@_inside_note_bool }
    \property_new:nnnn { postnotes/tagsup@noteid } { now } { 0 }
      { \l_postnotes_print_note_id_tl }
    \AddToHook { package/zref-user/after } [ postnotes/tagsup ]
      {
        \zref@newprop { postnotes@tagsup@noteid } [ 0 ]
          { \l_postnotes_print_note_id_tl }
        \AddToHook { postnotes/print/note/begin } [ postnotes/tagsup ]
          { \zref@localaddprop { main } { postnotes@tagsup@noteid } }
      }
%    \end{macrocode}
% Setup for \opt{label} and \opt{zlabel} options.
%    \begin{macrocode}
    \AddToHook { postnotes/note/store } [ postnotes/tagsup ]
      {
        \str_if_empty:NF \l_@@_note_label_str
          {
            \prop_gput:cnV
              { \@@_data_name:e { \l_postnotes_note_id_tl } }
              { label } \l_@@_note_label_str
          }
      }
    \AddToHook { package/zref-user/after } [ postnotes/tagsup ]
      {
        \AddToHook { postnotes/note/store } [ postnotes/tagsup ]
          {
            \str_if_empty:NF \l_@@_note_zlabel_str
              {
                \prop_gput:cnV
                  { \@@_data_name:e { \l_postnotes_note_id_tl } }
                  { zlabel } \l_@@_note_zlabel_str
              }
          }
      }
    \AddToHook { postnotes/print/note/begin } [ postnotes/tagsup ]
      {
        \@@_prop_get:nnN { \l_postnotes_print_note_id_tl }
          { label } \l_@@_restore_tmp_tl
        \tl_if_empty:NF \l_@@_restore_tmp_tl
          {
            \exp_args:Ne \property_record:nn
              { postnote@label@option. \l_@@_restore_tmp_tl }
              { postnotes/tagsup@noteid }
          }
        \@@_prop_get:nnN { \l_postnotes_print_note_id_tl }
          { zlabel } \l_@@_restore_tmp_tl
        \tl_if_empty:NF \l_@@_restore_tmp_tl
          {
            \exp_args:Ne \property_record:nn
              { postnote@zlabel@option. \l_@@_restore_tmp_tl }
              { postnotes/tagsup@noteid }
          }
      }
%    \end{macrocode}
% CHECK \pkg{latex-lab-footnotes} creates the footnote structure element
% (\texttt{FENote} tag) and adds to it a \texttt{/Ref} entry pointing to the
% structures of \emph{all} marks related to the note, and that includes
% \cs{footref}s.  I don't see anything stating something of the sort in the
% standards, the backref of the original mark is already a stretch.  I also
% fail to see why this is needed, and how it could be used.  But\dots{} I
% trust Ulrike knows better than me.
% \begin{macro}
%   {
%     \@@_tagsup_store_sctructnum:nN
%     \@@_tagsup_store_crossref:nN
%   }
%   \begin{syntax}
%     \cs{@@_tagsup_store_sctructnum:nN} \Arg{ref type} \Arg{ID number of note}
%     \cs{@@_tagsup_store_crossref:nN} \Arg{ref type} \Arg{ID number of note}
%   \end{syntax}
%   \meta{ref type} is either ``\texttt{postnote}'' or
%   ``\texttt{postnotemark}''.
%    \begin{macrocode}
    \prop_new:N \g_@@_tagsup_structnums_prop
    \cs_new_protected:Npn \@@_tagsup_store_sctructnum:nN #1#2
      {
        \prop_gput:Nee \g_@@_tagsup_structnums_prop
          { #1 . #2 } { \tag_get:n { struct_num } }
      }
    \prop_new:N \g_@@_tagsup_crossrefs_prop
    \cs_new_protected:Npn \@@_tagsup_store_crossref:nN #1#2
      {
        \prop_gput:Nee \g_@@_tagsup_crossrefs_prop
          { \tag_get:n { struct_num } } { #1 . #2 }
      }
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\@@_tagsup_gput_ref:nn}
%   \begin{syntax}
%     \cs{@@_tagsup_gput_ref:nn} \Arg{structnum refering from}
%     ~~~~\Arg{structnum being referenced to}
%   \end{syntax}
%   See \cs{__fnote_gput_ref:nn}.
%    \begin{macrocode}
    \cs_new_protected:Npn \@@_tagsup_gput_ref:nn #1#2
      {
        \tag_if_active:T
          { \tag_struct_gput:ene {#1} {ref} { \tag_struct_object_ref:e {#2} } }
      }
%    \end{macrocode}
% \end{macro}
% The actual inclusion of the reference has to be done at the end, since the
% \opt{ref} option called by \cs{tag_struct_begin:n} does not check if the
% variable to store the refs already exists, resulting in a clash if we add it
% immediately and a \cs{posnoteref} is made before \cs{printpostnotes}, and
% also so that the ``main'' reference always comes first at the list.
%    \begin{macrocode}
    \AddToHook { tagpdf/finish/before } [ postnotes/tagsup ]
      {
        \prop_map_inline:Nn \g_@@_tagsup_crossrefs_prop
          {
            \@@_tagsup_gput_ref:nn
              { \prop_item:Nn \g_@@_tagsup_structnums_prop {#2} }
              {#1}
          }
      }
%    \end{macrocode}
% \cs{postnoteref}
%    \begin{macrocode}
    \socket_new_plug:nnn { tagsupport/postnotes/postnoteref/begin } { default }
      {
        \tag_mc_end_push:
        \property_if_recorded:eeTF
          { postnote@label@innote. \l_@@_note_ref_label_tl }
          { postnotes/tagsup@noteid }
          {
%    \end{macrocode}
% Label coming from a \cs{label} inside the note.
%    \begin{macrocode}
            \tl_set:Ne \l_@@_tmpa_tl
              {
                \property_ref:ee
                  { postnote@label@innote. \l_@@_note_ref_label_tl }
                  { postnotes/tagsup@noteid }
              }
            \tag_struct_begin:n
              {
                tag = endnotemark ,
                ref = { postnote. \l_@@_tmpa_tl } ,
              }
            \@@_tagsup_store_crossref:nN
              { postnote } \l_@@_tmpa_tl
          }
          {
            \property_if_recorded:eeTF
              { postnote@label@option. \l_@@_note_ref_label_tl }
              { postnotes/tagsup@noteid }
              {
%    \end{macrocode}
% Label coming from a \opt{label} option.
%    \begin{macrocode}
                \tl_set:Ne \l_@@_tmpa_tl
                  {
                    \property_ref:ee
                      { postnote@label@option. \l_@@_note_ref_label_tl }
                      { postnotes/tagsup@noteid }
                  }
                \tag_struct_begin:n
                  {
                    tag = endnotemark ,
                    ref = { postnotemark. \l_@@_tmpa_tl } ,
                  }
                \@@_tagsup_store_crossref:nN
                  { postnotemark } \l_@@_tmpa_tl
              }
              { \tag_struct_begin:n { tag = endnotemark } }
          }
        \tag_mc_begin:n { }
      }
    \socket_new_plug:nnn { tagsupport/postnotes/postnoteref/end } { default }
      {
        \tag_mc_end:
        \tag_struct_end: % endnotemark
        \tag_mc_begin_pop:n { }
      }
    \socket_assign_plug:nn { tagsupport/postnotes/postnoteref/begin } { default }
    \socket_assign_plug:nn { tagsupport/postnotes/postnoteref/end } { default }
%    \end{macrocode}
% \cs{postnotezref}
%    \begin{macrocode}
    \AddToHook { package/zref-user/after } [ postnotes/tagsup ]
      {
        \socket_new_plug:nnn { tagsupport/postnotes/postnotezref/begin } { default }
          {
            \tag_mc_end_push:
            \zref@ifrefcontainsprop { \l_@@_note_zref_zlabel_tl }
              { postnotes@tagsup@noteid }
              {
%    \end{macrocode}
% Label coming from a \cs{zlabel} inside the note.
%    \begin{macrocode}
                \tl_set:Ne \l_@@_tmpa_tl
                  {
                    \zref@extract { \l_@@_note_zref_zlabel_tl }
                      { postnotes@tagsup@noteid }
                  }
                \tag_struct_begin:n
                  {
                    tag = endnotemark ,
                    ref = { postnote. \l_@@_tmpa_tl } ,
                  }
                \@@_tagsup_store_crossref:nN
                  { postnote } \l_@@_tmpa_tl
              }
              {
                \property_if_recorded:eeTF
                  { postnote@zlabel@option. \l_@@_note_zref_zlabel_tl }
                  { postnotes/tagsup@noteid }
                  {
%    \end{macrocode}
% Label coming from a \opt{zlabel} option.
%    \begin{macrocode}
                    \tl_set:Ne \l_@@_tmpa_tl
                      {
                        \property_ref:ee
                          {
                            postnote@zlabel@option.
                            \l_@@_note_zref_zlabel_tl
                          }
                          { postnotes/tagsup@noteid }
                      }
                    \tag_struct_begin:n
                      {
                        tag = endnotemark ,
                        ref = { postnotemark. \l_@@_tmpa_tl } ,
                      }
                    \@@_tagsup_store_crossref:nN
                      { postnotemark } \l_@@_tmpa_tl
                  }
                  { \tag_struct_begin:n { tag = endnotemark } }
              }
            \tag_mc_begin:n { }
          }
        \socket_new_plug:nnn { tagsupport/postnotes/postnotezref/end } { default }
          {
            \tag_mc_end:
            \tag_struct_end: % endnotemark
            \tag_mc_begin_pop:n { }
          }
        \socket_assign_plug:nn { tagsupport/postnotes/postnotezref/begin } { default }
        \socket_assign_plug:nn { tagsupport/postnotes/postnotezref/end } { default }
      }
  }
%    \end{macrocode}
%
%
% \section{Languages}
% \label{sec:languages}
%
% \begin{macro}[int]
%   {
%     \pntitle ,
%     \pnhdnotes ,
%     \pnhdtopage ,
%     \pnhdtopages ,
%   }
%   Set of language specific user variables.  They are used in the default
%   value of the \opt{heading} option and in \cs{pnheaderdefault} which,
%   ultimately, is also used in the same place.
%    \begin{macrocode}
\tl_new:N \pntitle
\tl_new:N \pnhdnotes
\tl_new:N \pnhdtopage
\tl_new:N \pnhdtopages
\tl_set:Nn \pntitle { Notes }
\tl_set:Nn \pnhdnotes { Notes }
\tl_set:Nn \pnhdtopage { to~page }
\tl_set:Nn \pnhdtopages { to~pages }
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\@@_define_language:nn}
%   Defines language specific values for \meta{postnote language} by storing a
%   set of assignments for the language specific variables in \meta{setup}.
%   \meta{postnote language} is an internal name, typically the ``main'' name
%   of the language, based on which we can set specific \pkg{babel} or
%   \pkg{polyglossia} languages or variants.
%     \begin{syntax}
%       \cs{@@_define_language:nn} \Arg{postnote language} \Arg{setup}
%     \end{syntax}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_define_language:nn #1#2
  {
    \tl_new:c { g_@@_language_ #1 _tl }
    \tl_gset:cn { g_@@_language_ #1 _tl } {#2}
  }
%    \end{macrocode}
% \end{macro}
%
%
% For \pkg{babel} we use the new hook system, it's clean, and avoids the
% \cs{addto} pitfalls.  The appropriate hook to use is
% \texttt{babel/\meta{language}/beforeextras} so that users can override it
% with a traditional
% \texttt{\textbackslash{}addto\textbackslash{}extras\meta{language}}.
%
% Note that, for \pkg{babel}, the captions are currently handled in two
% different ways -- the ``old way'' and the ``new way'' -- and which of them
% is used depends on the language.  Most still use the ``old way'', but the
% problem is that it is not universal.  And the ``new way'' uses a different
% naming scheme -- \texttt{\textbackslash{}\meta{language}\meta{caption}},
% which is meant to be set with \cs{setlocalecaption}, and not suitable for
% our needs.  The \texttt{\textbackslash{}extras\meta{language}} macros are
% meant for ``arbitrary'' code to be run when the language is selected, which
% is what we want.  The captions used to work in the same way, but no longer
% for languages which use the ``new way''.
%
% Note also that there seems to exist some qualms about \pkg{babel}'s
% \cs{addto}.  A number of packages define their own versions of it.  Do so at
% least \pkg{varioref} (probably the original), \pkg{backref}, and
% \pkg{cleveref}.  The latter comments that \cs{addto} is ``flawed''.
% \pkg{babel} itself comments the definition recognizing that there is an
% ``inconsistency'': depending on the case, the operation will be either local
% or global.  This is documented in the manual, which explains this
% inconsistent behavior is preserved for backward compatibility, and
% recommends \pkg{etoolbox}'s facilities if available.  \pkg{polyglossia} also
% recommends \pkg{etoolbox}'s \cs{gappto}.  All in all, if there's need to use
% the traditional way instead of the new hooks, just rely on \texttt{expl3}
% and use \cs{tl_gput_right:Nn}.
%
% \begin{macro}{\@@_set_babel_language:nn}
%   Sets \meta{babel language} to execute the setup defined by
%   \cs{@@_define_language:nn} for \meta{postnote language} at the
%   \texttt{babel/\meta{language}/beforeextras} hook.
%     \begin{syntax}
%       \cs{@@_set_babel_language:nn} \Arg{babel language} \Arg{postnote language}
%     \end{syntax}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_set_babel_language:nn #1#2
  {
    \ActivateGenericHook { babel/#1/beforeextras }
    \exp_args:Nnv \AddToHook { babel/#1/beforeextras }
      { g_@@_language_ #2 _tl }
  }
%    \end{macrocode}
% \end{macro}
%
%
% \pkg{polyglossia} uses a similar set of macros for setting up languages as
% \pkg{babel} does.  However, the
% \texttt{\textbackslash{}blockextras@\meta{language}} macros are
% unfortunately internal (despite what the manual says, that's what the code
% does), thus requiring \cs{makeatletter}/\cs{makeatother} for user
% configuration, which would be an inconvenience.  On the other hand,
% \pkg{polyglossia}'s \texttt{\textbackslash{}captions\meta{language}} works
% as in \pkg{babel}'s ``old way'', meaning it is just a ``hook'' to which we
% can append some code.  So we use
% \texttt{\textbackslash{}captions\meta{language}} for \pkg{polyglossia}.
% Things may complicate here if there's need to set up different values for
% different language variants, since the hooks available are all necessarily
% internal, but I doubt we'll ever need variants for these simple strings.
%
% \begin{macro}{\@@_set_polyglossia_language:nn}
%   Sets \meta{polyglossia language} to execute the setup defined by
%   \cs{@@_define_language:nn} for \meta{postnote language} at the
%   \pkg{polyglossia} \texttt{\textbackslash{}captions\meta{language}} hook.
%     \begin{syntax}
%       \cs{@@_set_polyglossia_language:nn} \Arg{polyglossia language}
%       ~~\Arg{postnote language}
%     \end{syntax}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_set_polyglossia_language:nn #1#2
  {
    \AddToHook { package/polyglossia/after }
      {
        \exp_args:Nnv \csgappto { captions #1 }
          { g_@@_language_ #2 _tl }
      }
  }
%    \end{macrocode}
% \end{macro}
%
%
% \subsection*{English}
%
%    \begin{macrocode}
\@@_define_language:nn { english }
  {
    \tl_set:Nn \pntitle     { Notes }
    \tl_set:Nn \pnhdnotes   { Notes }
    \tl_set:Nn \pnhdtopage  { to~page }
    \tl_set:Nn \pnhdtopages { to~pages }
  }
\@@_set_babel_language:nn { english }    { english }
\@@_set_babel_language:nn { british }    { english }
\@@_set_babel_language:nn { american }   { english }
\@@_set_babel_language:nn { canadian }   { english }
\@@_set_babel_language:nn { australian } { english }
\@@_set_babel_language:nn { newzealand } { english }
\@@_set_babel_language:nn { UKenglish }  { english }
\@@_set_babel_language:nn { USenglish }  { english }
\@@_set_polyglossia_language:nn { english } { english }
%    \end{macrocode}
%
%
% \subsection*{Portuguese}
%
%    \begin{macrocode}
\@@_define_language:nn { portuguese }
  {
    \tl_set:Nn \pntitle     { Notas }
    \tl_set:Nn \pnhdnotes   { Notas }
    \tl_set:Nn \pnhdtopage  { da~página }
    \tl_set:Nn \pnhdtopages { das~páginas }
  }
\@@_set_babel_language:nn { portuguese } { portuguese }
\@@_set_babel_language:nn { brazilian }  { portuguese }
\@@_set_babel_language:nn { portuges }   { portuguese }
\@@_set_babel_language:nn { brazil }     { portuguese }
\@@_set_polyglossia_language:nn { portuguese } { portuguese }
%    \end{macrocode}
%
%
% \subsection*{French}
%
% French localization validated by \contributor{\username{Pika78}} at
% \githubissue{1}.
%
% \pkg{babel-french} also has \file{.ldf}s for \texttt{francais},
% \texttt{frenchb}, and \texttt{canadien}, but they are deprecated as options
% and, if used, they fall back to either \texttt{french} or \texttt{acadian}.
%
%    \begin{macrocode}
\@@_define_language:nn { french }
  {
    \tl_set:Nn \pntitle     { Notes }
    \tl_set:Nn \pnhdnotes   { Notes }
    \tl_set:Nn \pnhdtopage  { de~la~page }
    \tl_set:Nn \pnhdtopages { des~pages }
  }
\@@_set_babel_language:nn { french }  { french }
\@@_set_babel_language:nn { acadian } { french }
\@@_set_polyglossia_language:nn { french } { french }
%    \end{macrocode}
%
%
% \subsection*{German}
%
% German localization provided by \contributor{Herbert Voß} at
% \githubissue{2}.
%
% \pkg{babel-german} also has \file{.ldf}s for \texttt{germanb} and
% \texttt{ngermanb}, but they are deprecated as options and, if used, they
% fall back respectively to \texttt{german} and \texttt{ngerman}.
%
%    \begin{macrocode}
\@@_define_language:nn { german }
  {
    \tl_set:Nn \pntitle     { Endnoten }
    \tl_set:Nn \pnhdnotes   { Endnoten }
    \tl_set:Nn \pnhdtopage  { zu~Seite }
    \tl_set:Nn \pnhdtopages { zu~Seiten }
  }
\@@_set_babel_language:nn { german }       { german }
\@@_set_babel_language:nn { ngerman }      { german }
\@@_set_babel_language:nn { austrian }     { german }
\@@_set_babel_language:nn { naustrian }    { german }
\@@_set_babel_language:nn { swissgerman }  { german }
\@@_set_babel_language:nn { nswissgerman } { german }
\@@_set_polyglossia_language:nn { german } { german }
%    \end{macrocode}
%
%
%    \begin{macrocode}
%</package>
%    \end{macrocode}
%
%
% \PrintIndex
%
% \endinput
%
% Local Variables:
% jinx-local-words: "endnote endnotes"
% End:
