% Maintained by Matthew Bertucci, 2024-present
% Please report all issues and feature requests at https://github.com/mbertucci47/keytheorems
% This work is licensed under the LPPL version 1.3c or later: https://www.latex-project.org/lppl.txt
\NeedsTeXFormat{LaTeX2e}[2023-06-01]
\def\@keythms@date{2025-09-16}
\def\@keythms@version{0.3.2}
\ProvidesExplPackage{keytheorems}{\@keythms@date}{\@keythms@version}
  {l3keys interface to amsthm}

\IfFormatAtLeastTF { 2024-06-01 } { }
  {
    \RequirePackage{nameref} % to avoid ltproperties in code below
    \cs_generate_variant:Nn \cs_set:Npn { Npe }
    \cs_generate_variant:Nn \iow_shipout:Nn { Ne }
    \cs_generate_variant:Nn \keys_set:nn { ne }
    \cs_generate_variant:Nn \msg_warning:nnn { nne }
    \cs_generate_variant:Nn \tl_put_right:Nn { Ne }
    \cs_generate_variant:Nn \tl_gput_right:Nn { ce }
    \ProvideDocumentCommand \IfPackageLoadedT { m +m }
      { \IfPackageLoadedTF{#1}{#2}{ } }
    \ProvideDocumentCommand \IfPackageLoadedF { m +m }
      { \IfPackageLoadedTF{#1}{ }{#2} }
    \ProvideDocumentCommand \IfClassLoadedT { m +m }
      { \IfClassLoadedTF{#1}{#2}{ } }
    \ProvideDocumentCommand \IfClassLoadedWithOptionsT { m m +m }
      { \IfClassLoadedWithOptionsTF{#1}{#2}{#3}{ } }
    \ProvideDocumentCommand \IfPackageLoadedWithOptionsT { m m +m }
      { \IfPackageLoadedWithOptionsTF{#1}{#2}{#3}{ } }
  }
\cs_if_exist:NF \@gobble@som
  { % defined in ltsect.dtx 1.1g
    \DeclareExpandableDocumentCommand\@gobble@om{+o+m}{}
    \DeclareExpandableDocumentCommand\@gobble@som{s+o+m}{}
  }

\RequirePackage{aliascnt}
\RequirePackage{amsthm} % ams classes have way of ignoring this
\RequirePackage{refcount}
\RequirePackage{translations}

%%%%%%%%%%%%%%%%%%%%%%
%%% Error Messages %%%
%%%%%%%%%%%%%%%%%%%%%%

\msg_new:nnn { keytheorems } { thmtools-before }
  {
    keytheorems~is~not~compatible~with~thmtools.~
    Try~replacing~\protect\usepackage{thmtools}~with~
    \protect\usepackage[thmtools-compat]{keytheorems}.
  }
\msg_new:nnn { keytheorems } { thmtools-after }
  {
    keytheorems~is~not~compatible~with~thmtools.~
    This~will~not~work~as~you~think!~
    Try~replacing~\protect\usepackage{thmtools}~with~
    \protect\usepackage[thmtools-compat]{keytheorems}.
  }
\msg_new:nnn { keytheorems } { no-stored-theorem }
  {
    No~stored~theorem~'#1'~found!~
    Try~compiling~again.~If~that~doesn't~work,~
    check~the~spelling~of~'#1'.
  }
\msg_new:nnn { keytheorems } { no-prop-for-stored-theorem }
  {
    No~property~'#1'~found~for~stored~theorem~'#2'~\msg_line_context:.
  }
\msg_new:nnn { keytheorems } { stored-tag-taken }
  {
    The~tag~'#1'~has~already~been~used!~
    Each~value~of~the~'store'~key~must~be~unique.
  }
\msg_new:nnn { keytheorems } { store-reversed-not-got }
  {
    'store*=#1'~only~makes~sense~if~you've~called~\protect\getkeytheorem{#1}.~
    Check~that~\protect\getkeytheorem{#1}~is~called~and~compile~again.
  }
\msg_new:nnn { keytheorems } { restate-body-never-got }
  {
    With~'store*=#1',~\protect\getkeytheorem[body]{#1}~only~makes~sense~if~
    \protect\getkeytheorem{#1}~has~been~called.~
    Check~that~\protect\getkeytheorem{#1}~is~called~and~compile~again.
  }
\msg_new:nnn { keytheorems } { store-reversed-called-twice }
  {
    With~'store*=#1',~\protect\getkeytheorem{#1}~can~be~called~only~once.
  }
\msg_new:nnn { keytheorems } { undefined-thm-hook }
  {
    No~theorem~hook~'#1'~\msg_line_context:. \\
    Check~the~spelling. \\
    Should~be~one~of~'prehead',~'posthead',~'prefoot',~'postfoot',~or~'restated'.
  }
\msg_new:nnn { keytheorems } { refname-argcount }
  {
    '#1'~accepts~either~one~or~two~comma-separated~items~\msg_line_context:.
  }
\msg_new:nnn { keytheorems } { hyperref-Autoref }
  {
    You~have~not~loaded~hyperref.~The~\protect\Autoref\space command~needs~
    hyperref~to~work~\msg_line_context:.
  }
\msg_new:nnn { keytheorems } { no-Autorefname }
  {
    No~Autoref~name~for~'#1'~\msg_line_context:. \\
    Please~define~\c_backslash_str #1Autorefname.
  }
\msg_new:nnn { keytheorems } { ctrfmt-unnumbered }
  {
    Theorem~'#1'~is~not~numbered~\msg_line_context:. \\
    Using~'counter-format'~does~not~make~sense.
  }
\msg_new:nnn { keytheorems } { thmstyle-undefined }
  {
    Theorem~style~'#1'~undefined~\msg_line_context:. \\
    Use~\protect\newkeytheoremstyle\space instead.
  }
\msg_new:nnn { keytheorems } { thmstyle-defined }
  {
    Theorem~style~'#1'~already~defined~\msg_line_context:. \\
    Use~\protect\renewkeytheoremstyle\space instead.
  }
\msg_new:nnn { keytheorems } { inherit-thmstyle-undefined }
  {
    Theorem~style~'#1'~undefined~\msg_line_context:.
  }
\msg_new:nnn { keytheorems } { thm-undefined }
  {
    Command~\c_backslash_str #1~undefined~\msg_line_context:.~
    Use~\protect\newkeytheorem\space instead.
  }
\msg_new:nnn { keytheorems } { missing-ext-thlist }
  {
    File~'#1.thlist'~not~found~\msg_line_context:. \\
    Theorems~will~not~be~imported.
  }
\msg_new:nnn { keytheorems } { title-code-with-AMS }
  {
    The~'title-code'~key~has~no~effect~with~an~AMS~class.
  }
\msg_new:nnn { keytheorems } { no-predefined-translations }
  {
    Language~'#1'~does~not~have~predefined~translations.~
    Defaulting~to~English.
  }

% Error if thmtools loaded since compilation hangs.
% If thmtools loaded after, produce warning.
\IfPackageLoadedTF { thmtools }
  {
    \msg_fatal:nn { keytheorems } { thmtools-before }
  }
  {
    \hook_gput_code:nnn { package/thmtools/before } { . }
      {
        \msg_warning:nn { keytheorems } { thmtools-after }
      }
  }

%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Declare Variables %%%
%%%%%%%%%%%%%%%%%%%%%%%%%

\clist_new:N \l__keythms_tmpa_clist
\iow_new:N \g__keythms_tmpa_iow
\seq_new:N \l__keythms_tmpa_seq
\tl_new:N \l__keythms_tmpa_tl
\tl_new:N \l__keythms_tmpb_tl

\bool_new:N \g__keythms_listof_writefile_bool
\bool_new:N \g__keythms_thmtoolscompat_bool
\bool_new:N \l__keythms_listofheading_storereversed_bool
\bool_new:N \g__keythms_predefined_bool
\bool_new:N \l__keythms_thm_numbered_bool
\bool_new:N \l__keythms_thm_unlessunique_bool
\bool_new:N \l__keythms_thmuse_listhack_bool
\bool_new:N \l__keythms_thmuse_restating_bool
\clist_new:N \g__keythms_restatecounters_clist
\clist_new:N \l__keythms_thmstyle_savedkeys_clist
\dim_new:N \l__keythms_thm_currparindent_dim
\dim_new:N \l__keythms_thm_currparskip_dim
\int_new:N \l__keythms_thm_tcbstate_int
\prop_new:N \g__keythms_thmnames_prop
\prop_new:N \g__keythms_thmstyle_defaultkeys_prop
\prop_new:N \g__keythms_thmuse_othercounters_prop
\prop_new:N \l__keythms_restate_counters_prop
\tl_new:N \l__keythms_thm_currentthmstyle_tl
\tl_new:N \l__keythms_thm_defaultkeys_tl
\tl_new:N \l__keythms_thm_envname_tl
\tl_new:N \l__keythms_thm_tcbkeys_tl
\tl_new:N \l__keythms_thm_tempstyle_tl
\tl_new:N \l__keythms_thmstyle_defaultkeys_tl
\tl_new:N \l__keythms_thmstyle_lnotebrace_tl
\tl_new:N \l__keythms_thmstyle_rnotebrace_tl
\tl_new:N \l_keythms_thmuse_envname_tl
\tl_new:N \l__keythms_thmuse_defaultkeys_tl
\tl_new:N \g__keythms_thmuse_temprestatedata_tl
\tl_new:N \g__keythms_thmuse_temprestatedatareversed_tl

\newcounter{keythms_restate_dummyctr}
\cs_gset:Npn \theHkeythms_restate_dummyctr
  { restate.\arabic{keythms_restate_dummyctr} }
\cs_gset:Npn \thekeythms_restate_dummyctr { }
\newcounter{keythms_continues_dummyctr}
\cs_gset:Npn \theHkeythms_continues_dummyctr
  { continues.\arabic{keythms_continues_dummyctr} }
\cs_gset:Npn \thekeythms_continues_dummyctr { }
\newcounter{keythms_unnumbered_dummyctr}
\cs_gset:Npn \theHkeythms_unnumbered_dummyctr
  { unnumbered.\arabic{keythms_unnumbered_dummyctr} }
\cs_gset:Npn \thekeythms_unnumbered_dummyctr { }
\newcounter{keythms_manualnum_dummyctr}
\cs_gset:Npn \theHkeythms_manualnum_dummyctr
  { manualnum.\arabic{keythms_manualnum_dummyctr} }
\cs_gset:Npn \thekeythms_manualnum_dummyctr { }

\cs_generate_variant:Nn \hook_gput_code:nnn { nnv }
\cs_generate_variant:Nn \keys_precompile:nnN { ne, nVc }
\cs_generate_variant:Nn \prop_set_from_keyval:Nn { Ne }

%%%%%%%%%%%%%%
%%% Styles %%%
%%%%%%%%%%%%%%

\cs_new_protected:Npn \__keythms_thmstyle_setbraces:nn #1#2
  { % #1 = left brace, #2 = right brace
    \tl_set:Nn \l__keythms_thmstyle_lnotebrace_tl { #1 }
    \tl_set:Nn \l__keythms_thmstyle_rnotebrace_tl { #2 }
  }
\cs_new_protected:Npn \__keythms_thmstyle_savethmkey_reqval:n #1
  { % #1 = key value
    \clist_put_right:No \l__keythms_thmstyle_savedkeys_clist
      { \l_keys_key_str = { #1 } }
  }
\cs_new_protected:Npn \__keythms_thmstyle_savethmkey_optval:n #1
  { % #1 = key value
    \tl_if_empty:NTF \l_keys_value_tl
      {
        \clist_put_right:No \l__keythms_thmstyle_savedkeys_clist
          { \l_keys_key_str }
      }
      {
        \clist_put_right:No \l__keythms_thmstyle_savedkeys_clist
          { \l_keys_key_str = { #1 } }
      }
  }

\keys_define:nn { keytheorems/thmstyle }
  {
    bodyfont      .tl_set:N = \l__keythms_thmstyle_bodyfont_tl,
    bodyfont      .value_required:n = true,
    break         .meta:n   = { postheadspace = \newline }, % add error if postheadspace set
    break         .value_forbidden:n = true,
    headfont      .tl_set:N = \l__keythms_thmstyle_headfont_tl,
    headfont      .value_required:n = true,
    headformat    .meta:n   = { headstyle = {#1} }, % extra braces are necessary! Otherwise breaks if #1 contains comma
    headformat    .value_required:n = true,
    headindent    .tl_set:N = \l__keythms_thmstyle_headindent_tl,
    headindent    .value_required:n = true,
    headpunct     .tl_set:N = \l__keythms_thmstyle_headpunct_tl,
    headpunct     .value_required:n = true,
    headstyle     .choice:,
    headstyle / margin .code:n =
      {
        \cs_set:Nn \keythms_thmstyle_headcmd:nnn
          {
            \makebox[0pt][r]{
              \keythms_thmstyle_thmnumber:n {
                \group_begin: \exp_not:V \l__keythms_thmstyle_numberfont_tl
                ##2 ~ \group_end: }
              }
            \NAME\NOTE
          }
      },
    headstyle / swapnumber .code:n =
      {
        \cs_set:Nn \keythms_thmstyle_headcmd:nnn
          {
            \keythms_thmstyle_thmnumber:n {
              \group_begin: \exp_not:V \l__keythms_thmstyle_numberfont_tl
              ##2 ~ \group_end: }
              \NAME\NOTE
          }
      },
    headstyle / unknown .cs_set:Np = \keythms_thmstyle_headcmd:nnn #1#2#3,
    headstyle     .value_required:n = true,
    inherit-style .code:n =
      {
        \tl_if_exist:cTF { g__keythms_thmstyle_#1_metakeys_tl }
          {
            \keys_set:nv { keytheorems/thmstyle }
              { g__keythms_thmstyle_#1_metakeys_tl }
          }
          { \msg_error:nnn { keytheorems } { inherit-thmstyle-undefined } { #1 } }
      },
    inherit-style .value_required:n = true,
    notebraces    .code:n   = \exp_after:wN \__keythms_thmstyle_setbraces:nn #1,
    notebraces    .value_required:n = true,
    notefont      .tl_set:N = \l__keythms_thmstyle_notefont_tl,
    notefont      .value_required:n = true,
    noteseparator .tl_set:N = \l__keythms_thmstyle_noteseparator_tl,
    noteseparator .value_required:n = true,
    numberfont    .tl_set:N = \l__keythms_thmstyle_numberfont_tl,
    numberfont    .value_required:n = true,
    postheadspace .tl_set:N = \l__keythms_thmstyle_postheadspace_tl,
    postheadspace .value_required:n = true,
    spaceabove    .tl_set:N = \l__keythms_thmstyle_spaceabove_tl,
    spaceabove    .value_required:n = true,
    spacebelow    .tl_set:N = \l__keythms_thmstyle_spacebelow_tl,
    spacebelow    .value_required:n = true,
    % thm keys that are saved for later
    counter-format        .code:n = \__keythms_thmstyle_savethmkey_reqval:n { #1 },
    counter-format        .value_required:n = true,
    leftmargin            .code:n = \__keythms_thmstyle_savethmkey_reqval:n { #1 },
    leftmargin            .value_required:n = true,
    margin                .code:n = \__keythms_thmstyle_savethmkey_reqval:n { #1 },
    margin                .value_required:n = true,
    numbered              .code:n = \__keythms_thmstyle_savethmkey_optval:n { #1 },
    numberlike            .code:n = \__keythms_thmstyle_savethmkey_reqval:n { #1 },
    numberlike            .value_required:n = true,
    numberwithin          .code:n = \__keythms_thmstyle_savethmkey_reqval:n { #1 },
    numberwithin          .value_required:n = true,
    parent                .code:n = \__keythms_thmstyle_savethmkey_reqval:n { #1 },
    parent                .value_required:n = true,
    postfoothook          .code:n = \__keythms_thmstyle_savethmkey_reqval:n { #1 },
    postfoothook          .value_required:n = true,
    postheadhook          .code:n = \__keythms_thmstyle_savethmkey_reqval:n { #1 },
    postheadhook          .value_required:n = true,
    prefoothook           .code:n = \__keythms_thmstyle_savethmkey_reqval:n { #1 },
    prefoothook           .value_required:n = true,
    preheadhook           .code:n = \__keythms_thmstyle_savethmkey_reqval:n { #1 },
    preheadhook           .value_required:n = true,
    qed                   .code:n =
      { % qed needs special treatment to distinguish qed from qed={}
        \tl_if_novalue:nTF { #1 }
          {
            \clist_put_right:No \l__keythms_thmstyle_savedkeys_clist
              { \l_keys_key_str }
          }
          {
            \clist_put_right:No \l__keythms_thmstyle_savedkeys_clist
              { \l_keys_key_str = { #1 } }
          }
      },
    qed                   .default:o = \c_novalue_tl,
    rightmargin           .code:n = \__keythms_thmstyle_savethmkey_reqval:n { #1 },
    rightmargin           .value_required:n = true,
    sharenumber           .code:n = \__keythms_thmstyle_savethmkey_reqval:n { #1 },
    sharenumber           .value_required:n = true,
    sibling               .code:n = \__keythms_thmstyle_savethmkey_reqval:n { #1 },
    sibling               .value_required:n = true,
    tcolorbox             .code:n = \__keythms_thmstyle_savethmkey_optval:n { #1 },
    tcolorbox-no-titlebar .code:n = \__keythms_thmstyle_savethmkey_optval:n { #1 },
    within                .code:n = \__keythms_thmstyle_savethmkey_reqval:n { #1 },
    within                .value_required:n = true,
  }

\cs_new_protected:Nn \keythms_thmstyle_thmname:n { \thmname{#1} }
\cs_new_protected:Nn \keythms_thmstyle_thmnumber:n { \thmnumber{#1} }
\cs_new_protected:Nn \keythms_thmstyle_thmnote:n { \thmnote{#1} }

\cs_new:Npn \keythms_thmstyle_headcmd_default:nnn #1#2#3
  {
    \keythms_thmstyle_thmname:n { #1 }
    \keythms_thmstyle_thmnumber:n
      { ~
        \group_begin:
        \exp_not:V \l__keythms_thmstyle_numberfont_tl
        #2
        \group_end:
      }
    \keythms_thmstyle_thmnote:n
      { \exp_not:V \l__keythms_thmstyle_noteseparator_tl
        \group_begin: % group so notefont doesn't affect headpunct
        \exp_not:V \l__keythms_thmstyle_notefont_tl
        \l__keythms_thmstyle_lnotebrace_tl #3 \l__keythms_thmstyle_rnotebrace_tl
        \group_end:
      }
  }

\prop_gset_from_keyval:Nn \g__keythms_thmstyle_defaultkeys_prop
  { % support files may overwrite these defaults
    bodyfont      = \itshape,
    headfont      = \bfseries,
    headindent    = 0pt,
    headpunct     = {.},
    headstyle     = \keythms_thmstyle_headcmd_default:nnn{#1}{#2}{#3},
    notebraces    = {(}{)},
    notefont      = \fontseries\mddefault\upshape,
    noteseparator = {~},
    numberfont    = \upshape,
    postheadspace = 5pt plus 1pt minus 1pt,
    spaceabove    = {}, % empty means default (works for AMS classes too)
    spacebelow    = {}, % empty means default (works for AMS classes too)
  }
\hook_gput_code:nnn { package/keytheorems/after } { . }
  { % need to defer to wait for support files
    \keys_precompile:neN { keytheorems/thmstyle }
      { \prop_to_keyval:N \g__keythms_thmstyle_defaultkeys_prop }
      \l__keythms_thmstyle_defaultkeys_tl
  }

\NewDocumentCommand \newkeytheoremstyle { m +m }
  {
    \cs_if_free:cTF { th@ #1 }
      { \keythms_thmstyle_declarestyle:nn { #1 } { #2 } }
      { \msg_error:nnn { keytheorems } { thmstyle-defined } { #1 } }
  }
\NewDocumentCommand \renewkeytheoremstyle { m +m }
  {
    \cs_if_free:cTF { th@ #1 }
      { \msg_error:nnn { keytheorems } { thmstyle-undefined } { #1 } }
      { \keythms_thmstyle_declarestyle:nn { #1 } { #2 } }
  }
\NewDocumentCommand \providekeytheoremstyle { m +m }
  {
    \cs_if_free:cT { th@ #1 }
      { \keythms_thmstyle_declarestyle:nn { #1 } { #2 } }
  }
\NewDocumentCommand \declarekeytheoremstyle { m +m }
  {
    \keythms_thmstyle_declarestyle:nn { #1 } { #2 }
  }

\@onlypreamble \newkeytheoremstyle
\@onlypreamble \renewkeytheoremstyle
\@onlypreamble \providekeytheoremstyle
\@onlypreamble \declarekeytheoremstyle

\cs_new_eq:NN \__keythms_thmstyle_new:nnnnnnnnn \newtheoremstyle
\cs_generate_variant:Nn \__keythms_thmstyle_new:nnnnnnnnn { nVVVVVVVe }

\tl_put_right:Nn \l_text_expand_exclude_tl { \thmnote \thmnumber \thmname }
% ^ allows \thmnote, etc. to work in headstyle; hope no bad side effects!
\cs_new_protected:Npn \keythms_thmstyle_declarestyle:nn #1#2
  { % user is in charge of spacing with \NAME and \NUMBER (thmtools compat...)
    \cs_set:Npn \NAME { \keythms_thmstyle_thmname:n { ####1 } }
    \cs_set:Npn \NUMBER
      {
        \keythms_thmstyle_thmnumber:n
          {
            \group_begin:
            \exp_not:V \l__keythms_thmstyle_numberfont_tl
            ####2
            \group_end:
          }
      }
    \cs_set:Npn \NOTE
      {
        \keythms_thmstyle_thmnote:n
          { \exp_not:V \l__keythms_thmstyle_noteseparator_tl
            \group_begin: % group so notefont doesn't affect headpunct
            \exp_not:V \l__keythms_thmstyle_notefont_tl
            \l__keythms_thmstyle_lnotebrace_tl
            ####3
            \l__keythms_thmstyle_rnotebrace_tl
            \group_end:
          }
      }
    \clist_clear:N \l__keythms_thmstyle_savedkeys_clist
    \tl_use:N \l__keythms_thmstyle_defaultkeys_tl
    \keys_set:nn { keytheorems/thmstyle } { #2 }
    \__keythms_thmstyle_new:nVVVVVVVe { #1 }
      \l__keythms_thmstyle_spaceabove_tl
      \l__keythms_thmstyle_spacebelow_tl
      \l__keythms_thmstyle_bodyfont_tl
      \l__keythms_thmstyle_headindent_tl
      \l__keythms_thmstyle_headfont_tl
      \l__keythms_thmstyle_headpunct_tl
      \l__keythms_thmstyle_postheadspace_tl
      { \text_expand:n { \keythms_thmstyle_headcmd:nnn{##1}{##2}{##3} } }
    % Define inherit-style key
    \tl_gclear_new:c { g__keythms_thmstyle_#1_metakeys_tl }
    \tl_gset:cn { g__keythms_thmstyle_#1_metakeys_tl } { #2 }
    \tl_clear_new:c { l__keythms_thmstyle_#1_savedthmkeys_tl }
    \keys_precompile:nVc { keytheorems/thm }
      \l__keythms_thmstyle_savedkeys_clist
      { l__keythms_thmstyle_#1_savedthmkeys_tl }
    \tl_if_empty:NF \l__keythms_thmstyle_spaceabove_tl
      {
        \skip_zero_new:c { g__keythms_thmstyle_#1_tcbspaceabove_skip }
        \skip_set_eq:cN { g__keythms_thmstyle_#1_tcbspaceabove_skip }
          \l__keythms_thmstyle_spaceabove_tl
      }
    \tl_if_empty:NF \l__keythms_thmstyle_spacebelow_tl
      {
        \skip_zero_new:c { g__keythms_thmstyle_#1_tcbspacebelow_skip }
        \skip_set_eq:cN { g__keythms_thmstyle_#1_tcbspacebelow_skip }
          \l__keythms_thmstyle_spacebelow_tl
      }
    \cs_undefine:N \NAME % undefine to prevent conflicts
    \cs_undefine:N \NUMBER
    \cs_undefine:N \NOTE
  }

% set up plain, definition, and remark for inherit-style
\tl_new:N \g__keythms_thmstyle_plain_metakeys_tl
\tl_new:N \g__keythms_thmstyle_definition_metakeys_tl
\tl_new:N \g__keythms_thmstyle_remark_metakeys_tl
\tl_gset:Nn \g__keythms_thmstyle_definition_metakeys_tl { bodyfont=\normalfont }
\tl_gset:Nn \g__keythms_thmstyle_remark_metakeys_tl
  {
    bodyfont   = \normalfont,
    headfont   = \itshape,
    spaceabove = 0.5\topsep,
    spacebelow = 0.5\topsep,
  }

%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Defining Theorems %%%
%%%%%%%%%%%%%%%%%%%%%%%%%

\cs_new_protected:Npn \__keythms_thm_setrefnames:nn #1#2
  { % use \seq_set_split instead of clist functions to preserve empty entries
    \seq_set_split:Nnn \l__keythms_tmpa_seq { , } { #2 }
    \int_compare:nNnTF { \seq_count:N \l__keythms_tmpa_seq } = { 2 }
      {
        \__keythms_thm_setrefnames_auxII:nee { #1 }
          { \seq_item:Nn \l__keythms_tmpa_seq { 1 } }
          { \seq_item:Nn \l__keythms_tmpa_seq { 2 } }
      }
      {
        \int_compare:nNnTF { \seq_count:N \l__keythms_tmpa_seq } = { 1 }
          {
            \__keythms_thm_setrefnames_auxI:ne { #1 }
              { \seq_item:Nn \l__keythms_tmpa_seq { 1 } }
          }
          { \msg_error:nnn { keytheorems } { refname-argcount } { refname } }
      }
  }
\cs_generate_variant:Nn \__keythms_thm_setrefnames:nn { nV }
\cs_new_protected:Npn \__keythms_thm_setrefnames_auxI:nn #1#2
  {
    \cs_set:cpn { #1 autorefname } { #2 }
    \IfPackageLoadedT { cleveref }
      {
        \crefname{#1}{#2}{\textbf{??~(pl.~#2)}}
      }
    \IfPackageLoadedT { zref-clever }
      {
        \zcRefTypeSetup{#1}{ name-sg=#2 }
      }
  }
\cs_new_protected:Npn \__keythms_thm_setrefnames_auxII:nnn #1#2#3
  {
    \cs_set:cpn { #1 autorefname } { #2 }
    \IfPackageLoadedT { cleveref }
      {
        \crefname{#1}{#2}{#3}
      }
    \IfPackageLoadedT { zref-clever }
      {
        \zcRefTypeSetup{#1}{ name-sg=#2, name-pl=#3 }
      }
  }
\cs_generate_variant:Nn \__keythms_thm_setrefnames_auxI:nn { ne }
\cs_generate_variant:Nn \__keythms_thm_setrefnames_auxII:nnn { nee }

\cs_new_protected:Npn \__keythms_thm_setRefnames:nn #1#2
  { % use \seq_set_split instead of clist functions to preserve empty entries
    \seq_set_split:Nnn \l__keythms_tmpa_seq { , } { #2 }
    \int_compare:nNnTF { \seq_count:N \l__keythms_tmpa_seq } = { 2 }
      {
        \__keythms_thm_setRefnames_auxII:nee { #1 }
          { \seq_item:Nn \l__keythms_tmpa_seq { 1 } }
          { \seq_item:Nn \l__keythms_tmpa_seq { 2 } }
      }
      {
        \int_compare:nNnTF { \seq_count:N \l__keythms_tmpa_seq } = { 1 }
          {
            \__keythms_thm_setRefnames_auxI:ne { #1 }
              { \seq_item:Nn \l__keythms_tmpa_seq { 1 } }
          }
          { \msg_error:nnn { keytheorems } { refname-argcount } { Refname } }
      }
  }
\cs_generate_variant:Nn \__keythms_thm_setRefnames:nn { nV }
\cs_new_protected:Npn \__keythms_thm_setRefnames_auxI:nn #1#2
  {
    \cs_set:cpn { #1 Autorefname } { #2 }
    \IfPackageLoadedT { cleveref }
      {
        \Crefname{#1}{#2}{\textbf{??~(pl.~#2)}}
      }
    \IfPackageLoadedT { zref-clever }
      {
        \zcRefTypeSetup{#1}{ Name-sg=#2 }
      }
  }
\cs_new_protected:Npn \__keythms_thm_setRefnames_auxII:nnn #1#2#3
  {
    \cs_set:cpn { #1 Autorefname } { #2 }
    \IfPackageLoadedT { cleveref }
      {
        \Crefname{#1}{#2}{#3}
      }
    \IfPackageLoadedT { zref-clever }
      {
        \zcRefTypeSetup{#1}{ Name-sg=#2, Name-pl=#3 }
      }
  }
\cs_generate_variant:Nn \__keythms_thm_setRefnames_auxI:nn { ne }
\cs_generate_variant:Nn \__keythms_thm_setRefnames_auxII:nnn { nee }

% this step is separate from above because we don't want to clobber cleveref's
% plural/capitalization defaults by unnecessarily calling \crefname
\cs_new_protected:Npn \__keythms_thm_setrefnamedefaults:nn #1#2
  { % \autoref and \Autoref
    \cs_set:cpe { #1 autorefname } { \text_lowercase:n { #2 } }
    \cs_set:cpe { #1 Autorefname } { \text_titlecase_first:n { #2 } }
    % zref-clever
    \IfPackageLoadedT { zref-clever }
      {
        \exp_args:Nne \zcRefTypeSetup { #1 }
          {
            name-sg = \exp_not:v { #1 autorefname },
            Name-sg = \exp_not:v { #1 Autorefname },
          }
      }
  }
\cs_generate_variant:Nn \__keythms_thm_setrefnamedefaults:nn { nV }

\keys_define:nn { keytheorems/thm }
  {
    counter-format .tl_set:N  = \l__keythms_thm_ctrfmt_tl,
    counter-format .value_required:n = true,
    heading        .meta:n    = { name = {#1} },
    heading        .value_required:n = true,
    leftmargin     .dim_set:N = \l__keythms_thm_leftmargin_dim,
    leftmargin     .value_required:n = true,
    margin         .meta:n    = { leftmargin=#1, rightmargin=#1 },
    margin         .value_required:n = true,
    name           .tl_set:N  = \l__keythms_thm_name_tl,
    name           .value_required:n = true,
    numbered       .choice:,
    numbered       .default:n = true,
    numbered / false .code:n  = \bool_set_false:N \l__keythms_thm_numbered_bool,
    numbered / no    .meta:n  = { numbered = false },
    numbered / true  .code:n  = \bool_set_true:N \l__keythms_thm_numbered_bool,
    numbered / unless-unique .code:n = 
      {
        \bool_set_true:N \l__keythms_thm_unlessunique_bool
      },
    numbered / unless~unique .meta:n = { numbered = unless-unique },
    numbered / yes .meta:n    = { numbered = true },
    numberlike     .meta:n    = { sibling = {#1} },
    numberlike     .value_required:n = true,
    numberwithin   .meta:n    = { parent = {#1} },
    numberwithin   .value_required:n = true,
    parent         .tl_set:N  = \l__keythms_thm_parent_tl,
    parent         .value_required:n = true,
    postfoothook   .tl_set:N  = \l__keythms_thm_postfoothook_tl,
    postfoothook   .value_required:n = true,
    postheadhook   .tl_set:N  = \l__keythms_thm_postheadhook_tl,
    postheadhook   .value_required:n = true,
    prefoothook    .tl_set:N  = \l__keythms_thm_prefoothook_tl,
    prefoothook    .value_required:n = true,
    preheadhook    .tl_set:N  = \l__keythms_thm_preheadhook_tl,
    preheadhook    .value_required:n = true,
    qed            .tl_set:N  = \l__keythms_thm_qed_tl,
    qed            .default:n = { \qedsymbol },
    % ^ distinguish between 'qed' and 'qed={}'
    refname        .tl_set:N  = \l__keythms_thm_refname_tl,
    refname        .value_required:n = true,
    Refname        .tl_set:N  = \l__keythms_thm_Refname_tl,
    Refname        .value_required:n = true,
    rightmargin    .dim_set:N = \l__keythms_thm_rightmargin_dim,
    rightmargin    .value_required:n = true,
    sharenumber    .meta:n    = { sibling = {#1} },
    sharenumber    .value_required:n = true,
    sibling        .tl_set:N  = \l__keythms_thm_sibling_tl,
    sibling        .value_required:n = true,
    style          .tl_set:N  = \l__keythms_thm_style_tl,
    style          .value_required:n = true,
    style          .groups:n  = { style-comes-first },
    tcolorbox      .code:n    =
      {
        \int_set:Nn \l__keythms_thm_tcbstate_int { 1 }
        \tl_set:Nn \l__keythms_thm_tcbkeys_tl { #1 }
      },
    tcolorbox      .default:n = {},
    tcolorbox-no-titlebar .code:n =
      {
        \int_set:Nn \l__keythms_thm_tcbstate_int { 2 }
        \tl_set:Nn \l__keythms_thm_tcbkeys_tl { #1 }
      },
    tcolorbox-no-titlebar .default:n = {},
    title          .meta:n    = { name = {#1} },
    title          .value_required:n = true,
    within         .meta:n    = { parent = {#1} },
    within         .value_required:n = true,
  }

\keys_precompile:nnN { keytheorems/thm }
  {
    counter-format = \q_no_value,
    margin         = 0pt,
    name           = \q_no_value,
    numbered       = true,
    parent         = {},
    postfoothook   = {},
    postheadhook   = {},
    prefoothook    = {},
    preheadhook    = {},
    qed            = \q_no_value,
    refname        = \q_no_value,
    Refname        = \q_no_value,
    sibling        = {},
    style          = {},
  }
  \l__keythms_thm_defaultkeys_tl

\cs_new_protected:Npn \__keythms_thm_makethmhooks:n #1
  {
    \hook_new_pair:nn { keytheorems/#1/prehead } { keytheorems/#1/postfoot }
    \hook_new_pair:nn { keytheorems/#1/posthead } { keytheorems/#1/prefoot }
    \hook_new:n { keytheorems/#1/restated }
  }

% Make generic theorem hooks
\__keythms_thm_makethmhooks:n { allthms }

\NewDocumentCommand \newkeytheorem { m +O{} }
  { % #1 = name, #2 = keys
    \clist_map_inline:nn { #1 } % define multiple theorems at once
      { \keythms_thm_newkeythm:nn { ##1 } { #2 } }
  }
\NewDocumentCommand \renewkeytheorem { m +O{} }
  { % #1 = name, #2 = keys
    \clist_map_inline:nn { #1 }
      { \keythms_thm_renewkeythm:nn { ##1 } { #2 } }
  }
\NewDocumentCommand \providekeytheorem { m +O{} }
  { % #1 = name, #2 = keys
    \clist_map_inline:nn { #1 }
      { \keythms_thm_providekeythm:nn { ##1 } { #2 } }
  }
\NewDocumentCommand \declarekeytheorem { m +O{} }
  { % #1 = name, #2 = keys
    \clist_map_inline:nn { #1 }
      { \keythms_thm_declarekeythm:nn { ##1 } { #2 } }
  }
\@onlypreamble \newkeytheorem
\@onlypreamble \renewkeytheorem
\@onlypreamble \providekeytheorem
\@onlypreamble \declarekeytheorem

% to prevent error when plain, remark, or definition style used
\tl_new:N \l__keythms_thmstyle_plain_savedthmkeys_tl
\tl_new:N \l__keythms_thmstyle_remark_savedthmkeys_tl
\tl_new:N \l__keythms_thmstyle_definition_savedthmkeys_tl

\cs_new_protected:Npn \keythms_thm_newkeythm:nn #1#2
  { % #1 = name, #2 = keys
    % Store envname
    \tl_set:Nn \l__keythms_thm_envname_tl { #1 }
    % Set up tl's for hooks; hooks will be created and added to at begindocument
    \tl_gclear_new:c { g__keythms_thm_preheadfromkeys_#1_tl }
    \tl_gclear_new:c { g__keythms_thm_postheadfromkeys_#1_tl }
    \tl_gclear_new:c { g__keythms_thm_prefootfromkeys_#1_tl }
    \tl_gclear_new:c { g__keythms_thm_postfootfromkeys_#1_tl }
    % Make unless-unique false by default (can't precompile this)
    \bool_set_false:N \l__keythms_thm_unlessunique_bool
    % Set default keys
    \tl_use:N \l__keythms_thm_defaultkeys_tl
    % Initialize tcb state to zero (1 is with title bar, 2 is without title bar)
    \int_zero:N \l__keythms_thm_tcbstate_int
    % First set style so we can pick up additional thm keys, then overwrite if necessary
    \keys_set_groups:nnn { keytheorems/thm } { style-comes-first } { #2 }
    % Store theorem style
    \tl_set:Ne \l__keythms_thm_currentthmstyle_tl { \the\thm@style }
    \tl_if_empty:NTF \l__keythms_thm_style_tl
      { % if \theoremstyle set, also use saved thm keys
        \tl_if_exist:cT {l__keythms_thmstyle_ \l__keythms_thm_currentthmstyle_tl _savedthmkeys_tl}
          { \tl_use:c {l__keythms_thmstyle_ \l__keythms_thm_currentthmstyle_tl _savedthmkeys_tl} }
      }
      {
        % Temporarily set theorem style
        \__keythms_theoremstyle:n { \l__keythms_thm_style_tl }
        % If thm keys given in style, call now (possibly overwritten in next step)
        % but don't error if user uses a style defined with just \newtheoremstyle
        \tl_if_exist:cT { l__keythms_thmstyle_ \l__keythms_thm_style_tl _savedthmkeys_tl }
          { \tl_use:c { l__keythms_thmstyle_ \l__keythms_thm_style_tl _savedthmkeys_tl } }
      }
    % Set env-specific keys
    \keys_set:nn { keytheorems/thm } { #2 }
    % Build tl for env-specific hooks; will be added to hooks at begindocument
    \tl_gput_right:cV { g__keythms_thm_preheadfromkeys_#1_tl } \l__keythms_thm_preheadhook_tl
    \tl_gput_right:cV { g__keythms_thm_postheadfromkeys_#1_tl } \l__keythms_thm_postheadhook_tl
    \tl_gput_right:cV { g__keythms_thm_prefootfromkeys_#1_tl } \l__keythms_thm_prefoothook_tl
    \tl_gput_right:cV { g__keythms_thm_postfootfromkeys_#1_tl } \l__keythms_thm_postfoothook_tl
    % Set name if none given
    \quark_if_no_value:NT \l__keythms_thm_name_tl % use quark so name={} is valid
      {
        % use e so \text_titlecase called only once per theorem definition,
        % not each time the theorem is used
        \tl_set:Ne \l__keythms_thm_name_tl 
          { \text_titlecase_first:n { #1 } }
      }
    % associate formatted name with envname in prop list
    \prop_gput:NeV \g__keythms_thmnames_prop { #1 } \l__keythms_thm_name_tl
    % Call correct \newtheorem variant
    \bool_if:NTF \l__keythms_thm_unlessunique_bool
      {
        % [unq] is required since aux is read at begindocument
        % (technically right before) which is after theorem is defined
        \RequirePackage[unq]{unique}
        \tl_if_empty:NTF \l__keythms_thm_parent_tl
          {
            \tl_gput_right:cn { g__keythms_thm_preheadfromkeys_#1_tl }
              { \setuniqmark { #1 } }
            \ifuniq{ #1 }
              { \bool_set_false:N \l__keythms_thm_numbered_bool }
              { \bool_set_true:N \l__keythms_thm_numbered_bool }
            \bool_if:NTF \l__keythms_thm_numbered_bool
              {
                \tl_if_empty:NTF \l__keythms_thm_sibling_tl
                  {
                    \__keythms_thm_new_numbered:nV { #1 } \l__keythms_thm_name_tl
                  }
                  {
                    \exp_args:NnV \newaliascnt { #1 } \l__keythms_thm_sibling_tl
                    \__keythms_thm_new_sibling:nVn { #1 }
                      \l__keythms_thm_name_tl { #1 }
                    \aliascntresetthe { #1 }
                  }
              }
              {
                \__keythms_thm_new_unnumbered:nV { #1 } \l__keythms_thm_name_tl
                \tl_gput_right:cn { g__keythms_thm_preheadfromkeys_#1_tl }
                  {
                    \keythms_if_restating:F
                      { \refstepcounter{ keythms_unnumbered_dummyctr } }
                  }
              }
          }
          {
            \__keythms_thm_new_uuwithparent:nVV { #1 }
              \l__keythms_thm_name_tl \l__keythms_thm_parent_tl
          }
      }
      {
        \bool_if:NTF \l__keythms_thm_numbered_bool
          {
            \tl_if_empty:NTF \l__keythms_thm_parent_tl
              {
                \tl_if_empty:NTF \l__keythms_thm_sibling_tl
                  {
                    \__keythms_thm_new_numbered:nV { #1 } \l__keythms_thm_name_tl
                  }
                  {
                    \exp_args:NnV \newaliascnt { #1 } \l__keythms_thm_sibling_tl
                    \__keythms_thm_new_sibling:nVn { #1 }
                      \l__keythms_thm_name_tl { #1 }
                    \aliascntresetthe { #1 }
                  }
              }
              {
                \__keythms_thm_new_parent:nVV { #1 }
                  \l__keythms_thm_name_tl \l__keythms_thm_parent_tl
              }
          }
          {
            \__keythms_thm_new_unnumbered:nV { #1 } \l__keythms_thm_name_tl
            \tl_gput_right:cn { g__keythms_thm_preheadfromkeys_#1_tl }
              {
                \keythms_if_restating:F
                  { \refstepcounter{ keythms_unnumbered_dummyctr } }
              }
          }
      }
    % Store theorem def and redefine it with keys
    \__keythms_keyify_theorem:n { #1 }
    % Set ref name defaults; may be overwritten in next step
    \__keythms_thm_setrefnamedefaults:nV { #1 } \l__keythms_thm_name_tl
    % Set ref names
    \quark_if_no_value:NF \l__keythms_thm_refname_tl
      { \__keythms_thm_setrefnames:nV { #1 } \l__keythms_thm_refname_tl }
    \quark_if_no_value:NF \l__keythms_thm_Refname_tl 
      { \__keythms_thm_setRefnames:nV { #1 } \l__keythms_thm_Refname_tl }
    % Set margins if needed
    \bool_lazy_or:nnT
      { ! \dim_compare_p:nNn { \l__keythms_thm_leftmargin_dim } = { 0pt } }
      { ! \dim_compare_p:nNn { \l__keythms_thm_rightmargin_dim } = { 0pt } }
      {
        \exp_args:NnVV \__keythms_thm_margincode:nnn { #1 }
          \l__keythms_thm_leftmargin_dim \l__keythms_thm_rightmargin_dim
      }
    % Set up qed if needed
    \quark_if_no_value:NF \l__keythms_thm_qed_tl
      {
        \exp_args:NnV \__keythms_thm_qedcode:nn { #1 } \l__keythms_thm_qed_tl
      }
    % Set up tcolorbox if needed
    \int_compare:nNnTF { \l__keythms_thm_tcbstate_int } = { 1 }
      {
        \exp_args:Nno \__keythms_thm_tcbcode:nn { #1 }
          { \l__keythms_thm_tcbkeys_tl }
      }
      {
        \int_compare:nNnT { \l__keythms_thm_tcbstate_int } = { 2 }
          {
            \exp_args:Nno \__keythms_thm_tcbnotitlebarcode:nn { #1 }
              { \l__keythms_thm_tcbkeys_tl }
          }
      }
    % Set counter format if needed
    \quark_if_no_value:NF \l__keythms_thm_ctrfmt_tl
      {
        \bool_if:NTF \l__keythms_thm_numbered_bool
          { \exp_args:NnV \cs_set:cpn { the #1 } \l__keythms_thm_ctrfmt_tl }
          { \msg_warning:nnn { keytheorems } { ctrfmt-unnumbered } { #1 } }
      }
    % Set up list-of definition
    \cs_gset:cpn { l@ #1 } { \keythms_listof_tocline: }
    % Set default list-of display command
    \__keythms_listof_show_aux:n { #1 }
    % Set theorem style back to original state if needed
    \tl_if_empty:NF \l__keythms_thm_style_tl
      { \__keythms_theoremstyle:V \l__keythms_thm_currentthmstyle_tl }
  }

\tl_const:Nn \c__keythms_hooksetup_tl
  {
    \prop_map_inline:Nn \g__keythms_thmnames_prop
      {
        \__keythms_thm_makethmhooks:n { #1 }
        \clist_map_inline:nn { prehead, posthead, prefoot, postfoot }
          {
            \tl_if_empty:cF { g__keythms_thm_##1fromkeys_#1_tl }
              {
                \hook_gput_code:nnv { keytheorems/#1/##1 } { keythms_hook_keys }
                  { g__keythms_thm_##1fromkeys_#1_tl }
              }
          }
        \use:c { g__keythms_thm_tcbpatch_#1_tl }
      }
    \cs_set_eq:NN \__keythms_thm_origtrivlist: \trivlist % for margin code below
  }
\hook_gput_code:nnn { begindocument/end } { . }
  { % /end for 'predefined'
    \tl_use:N \c__keythms_hooksetup_tl
  }

\cs_new_protected:Npn \__keythms_thm_margincode:nnn #1#2#3
  {
    \tl_gput_right:cn { g__keythms_thm_preheadfromkeys_#1_tl }
      {
        \dim_set_eq:NN \l__keythms_thm_currparindent_dim \parindent
        \dim_set_eq:NN \l__keythms_thm_currparskip_dim \parskip
        \cs_set_protected:Npn \trivlist
          {
            \list{ }
              {
                \dim_set:Nn \leftmargin { #2 }
                \dim_set:Nn \rightmargin { #3 }
                \dim_zero:N \labelwidth % trivlist does this; important for tcb-no-title
                % need to revert some adjustments \list makes (any more?)
                \int_gdecr:N \@listdepth % avoid changing format of inner lists
                \dim_set_eq:NN \listparindent \l__keythms_thm_currparindent_dim
                \dim_set_eq:NN \parsep \l__keythms_thm_currparskip_dim  
              }
          }
      }
    \tl_gput_right:cn { g__keythms_thm_postheadfromkeys_#1_tl }
      { \cs_set_eq:NN \trivlist \__keythms_thm_origtrivlist: }
  }

\tl_const:Nn \c__keythms_savedcmdssetup_tl
  { % use /end because hyperref redefines \Hy@theorem@makelinktarget in begindocument
    \cs_new_eq:NN \__keythms_thm_origdeferred@thm@head:n \deferred@thm@head
    \cs_new_eq:NN \__keythms_thm_origHy@theorem@makelinktarget:n \Hy@theorem@makelinktarget
  }
\hook_gput_code:nnn { begindocument/end } { . }
  { \tl_use:N \c__keythms_savedcmdssetup_tl }

\cs_new_protected:Npn \__keythms_thm_tcbcode:nn #1#2
  { % #1 = name, #2 = tcolorbox keys
    \tl_gput_right:cn { g__keythms_thm_preheadfromkeys_#1_tl }
      {
        \cs_set_eq:NN \deferred@thm@head \__keythms_thm_storedeferred@thm@head:n
        \cs_set_eq:NN \Hy@theorem@makelinktarget \use_none:n
        % % ^ don't like playing with hyperref internals... but don't see around
        % %   it because hyperref tries to add to para hook which doesn't work
        % %   when title set up the way we do it
      }
    \tl_gput_right:cn { g__keythms_thm_postheadfromkeys_#1_tl }
      {
        \cs_set_eq:NN \deferred@thm@head \__keythms_thm_origdeferred@thm@head:n
        \cs_set_eq:NN \Hy@theorem@makelinktarget \__keythms_thm_origHy@theorem@makelinktarget:n
      }
    \__keythms_thm_tcbshared:nn { #1 }
      {
        title={ \__keythms_thm_tcbtemphead: },
        #2
      }
    \bool_if:NT \l__keythms_thm_numbered_bool
      {
        \tl_gclear_new:c { g__keythms_thm_tcbpatch_#1_tl }
        \tl_gset:cn { g__keythms_thm_tcbpatch_#1_tl }
          {
            \IfPackageLoadedF { cleveref }
              { % hyperref doesn't patch \@thm if cleveref loaded
                \tcbset
                  {
                    keythms_tcb_#1/.append~style = % fix hyperlinking
                      { phantom={ \MakeLinkTarget*{\@currentHref} } }
                  }
              }
          }
      }
    \tl_gput_left:cn { g__keythms_thm_postheadfromkeys_#1_tl }
      { \begin{tcolorbox}[keythms_tcb_#1] }
    \tl_gput_right:cn { g__keythms_thm_prefootfromkeys_#1_tl }
      { \end{tcolorbox} }
  }
\cs_new_protected:Npn \__keythms_thm_tcbnotitlebarcode:nn #1#2
  { % #1 = name, #2 = tcolorbox keys
    \__keythms_thm_tcbshared:nn { #1 } { #2 }
    \tl_gclear_new:c { g__keythms_thm_tcbprehead_#1_tl }
    \tl_gset:cn { g__keythms_thm_tcbprehead_#1_tl }
      { \begin{tcolorbox}[keythms_tcb_#1] }
    \tl_gclear_new:c { g__keythms_thm_tcbpostfoot_#1_tl }
    \tl_gset:cn { g__keythms_thm_tcbpostfoot_#1_tl }
      { \end{tcolorbox} }
  }
\cs_new_protected:Npn \__keythms_thm_tcbshared:nn #1#2
  {
    \RequirePackage{tcolorbox}
    \tcbset
      {
        keythms_tcb_#1/.style =
          {
            savedelimiter=#1,
            #2
          }
      }
    \tl_if_empty:NTF \l__keythms_thm_style_tl
      {
        \tl_set_eq:NN \l__keythms_thm_tempstyle_tl
          \l__keythms_thm_currentthmstyle_tl
      }
      { \tl_set_eq:NN \l__keythms_thm_tempstyle_tl \l__keythms_thm_style_tl }
    \tl_gput_right:ce { g__keythms_thm_preheadfromkeys_#1_tl }
      { % don't mess with tcolorbox defaults unless explicitly asked to in style
        \exp_not:N \tl_put_right:cn { th@ \l__keythms_thm_tempstyle_tl }
          { \thm@preskip=0pt \thm@postskip=0pt }
      }
    \tl_if_exist:cT
      { g__keythms_thmstyle_ \l__keythms_thm_tempstyle_tl _tcbspaceabove_skip }
      {
        \exp_args:Ne \tcbset
          {
            keythms_tcb_#1/.prefix~style =
              {
                before~skip =
                  \skip_use:c { g__keythms_thmstyle_ \l__keythms_thm_tempstyle_tl _tcbspaceabove_skip }
              }
          }
      }
    \tl_if_exist:cT
      { g__keythms_thmstyle_ \l__keythms_thm_tempstyle_tl _tcbspacebelow_skip }
      {
        \exp_args:Ne \tcbset
          {
            keythms_tcb_#1/.prefix~style =
              {
                after~skip =
                  \skip_use:c { g__keythms_thmstyle_ \l__keythms_thm_tempstyle_tl _tcbspacebelow_skip }
              }
          }
      }
  }

\cs_new_protected:Npn \__keythms_thm_storedeferred@thm@head:n #1
  {
    \cs_set:Npn \__keythms_thm_tcbtemphead: { \normalfont #1 }
    \ignorespaces
  }
\cs_new_protected:Npn \__keythms_thm_qedcode:nn #1#2
  { % #1 = name, #2 = symbol
    \tl_gput_right:cn { g__keythms_thm_postheadfromkeys_#1_tl }
      {
        \tl_if_eq:nnF { #2 } { \qedsymbol } { \cs_set:Npn \qedsymbol { #2 } }
        \pushQED{\qed}
      }
    \tl_gclear_new:c { g__keythms_thm_QEDprefoot_#1_tl }
    \tl_gset:cn { g__keythms_thm_QEDprefoot_#1_tl }
      {
        \tl_if_eq:nnF { #2 } { \qedsymbol } { \cs_set:Npn \qedsymbol { #2 } }
        \popQED
      }
  }

\cs_new_protected:Npn \__keythms_nocheck_removefromreset:nn #1#2
  { % need to fake @ckpt counter
    \group_begin:
    \cs_if_exist:cF { c@ #2 } { \cs_set:cpn { c@ #2 } { } }
    \@removefromreset{ #1 }{ #2 }
    \group_end:
  }

\cs_new_protected:Npn \keythms_thm_renewkeythm:nn #1#2
  { % #1 = name, #2 = keys
    \cs_if_exist:cTF { #1 }
      { \keythms_thm_declarekeythm:nn { #1 } { #2 } }
      { \msg_error:nnn { keytheorems } { thm-undefined} { #1 } }
  }
\cs_new_protected:Npn \keythms_thm_providekeythm:nn #1#2
  { % #1 = name, #2 = keys
    \cs_if_free:cT { #1 } { \keythms_thm_newkeythm:nn { #1 } { #2 } }
  }
\cs_new_protected:Npn \keythms_thm_declarekeythm:nn #1#2
  { % #1 = name, #2 = keys
    \cs_undefine:c { #1 }
    \cs_undefine:c { c@ #1 }
    \cs_undefine:c { the #1 }
    \tl_if_exist:cT { g__keythms_thm_#1_parent_tl }
      { % remove parent counter binding
        \exp_args:Nnv \@removefromreset { #1 } { g__keythms_thm_#1_parent_tl }
      }
    \__keythms_nocheck_removefromreset:nn { #1 } { @ckpt }
    \cs_undefine:c { g__keythms_thm_QEDprefoot_#1_tl } % These are only
    \cs_undefine:c { g__keythms_thm_tcbpatch_#1_tl } % conditionally defined
    \cs_undefine:c { g__keythms_thm_tcbprehead_#1_tl } % Need to undefine
    \cs_undefine:c { g__keythms_thm_tcbpostfoot_#1_tl } % so old defs not used
    \keythms_thm_newkeythm:nn { #1 } { #2 }
  }

\cs_new_eq:NN \__keythms_theoremstyle:n \theoremstyle
\cs_generate_variant:Nn \__keythms_theoremstyle:n { V }

\cs_new_eq:NN \__keythms_thm_new:w \newtheorem

\cs_new_protected:Npn \__keythms_thm_new_numbered:nn #1#2
  { \__keythms_thm_new:w { #1 } { #2 } }
\cs_generate_variant:Nn \__keythms_thm_new_numbered:nn { nV }

\cs_new_protected:Npn \__keythms_thm_new_unnumbered:nn #1#2
  { \__keythms_thm_new:w* { #1 } { #2 } }
\cs_generate_variant:Nn \__keythms_thm_new_unnumbered:nn { nV }

\cs_new_protected:Npn \__keythms_thm_new_parent:nnn #1#2#3
  {
    % for \renewkeytheorem need to know parent key if set
    \tl_gclear_new:c { g__keythms_thm_#1_parent_tl }
    \tl_gset:cn { g__keythms_thm_#1_parent_tl } { #3 }
    \__keythms_thm_new:w { #1 } { #2 } [ #3 ]
  }
\cs_generate_variant:Nn \__keythms_thm_new_parent:nnn { nVV }

\cs_new_protected:Npn \__keythms_thm_new_sibling:nnn #1#2#3
  { \__keythms_thm_new:w { #1 } [ #3 ] { #2 } }
\cs_generate_variant:Nn \__keythms_thm_new_sibling:nnn { nV }

\cs_new_protected:Npn \__keythms_thm_new_uuwithparent:nnn #1#2#3
  {
    \cs_undefine:c { keythms_orig_nonumber_#1 } % for renew, declare
    \__keythms_thm_new_unnumbered:nn { keythms_orig_nonumber_#1 } { #2 }
    \__keythms_thm_new_parent:nnn { #1 } { #2 } { #3 }
    \DeclareEnvironmentCopy { keythms_orig_withparent_#1 } { #1 }
    \renewenvironment { #1 } % opt arg is implicit
      {
        \setuniqmark{ #1. \use:c { the #3 } }
        \ifuniq{ #1. \use:c { the #3 } }
          {
            \keythms_if_restating:F
              { \refstepcounter{ keythms_unnumbered_dummyctr } }
            \IfPackageLoadedT { tcolorbox }
              { \tcbset{keythms_tcb_#1/.append~style=nophantom} }
            % ^ otherwise we try to set two identical anchors
            \begin{keythms_orig_nonumber_#1}
          }
          {
            \begin{keythms_orig_withparent_#1}
          }
      }
      {
        \ifuniq{ #1. \use:c { the #3 } }
          { \end{keythms_orig_nonumber_#1} }
          { \end{keythms_orig_withparent_#1} }
      }
  }
\cs_generate_variant:Nn \__keythms_thm_new_uuwithparent:nnn { nVV }

% for getting notes with continues*, use nameref if available, otherwise ltproperties
\tl_const:Nn \c__keythms_notesetup_tl
  {
    \IfPackageLoadedTF { nameref }
      { % only need to record short-note if nameref loaded
        \cs_new:Npn \__keythms_thmuse_recordnote:
          {
            \tl_if_empty:NF \l__keythms_thmuse_shortnote_tl
              {
                \RecordProperties
                  { keythms_recordednote_\l__keythms_thmuse_label_tl }
                  { keytheorems/recordedshortnote }
              }
          }
        \cs_new:Npn \__keythms_getrecordednote:n #1
          {
            \getrefbykeydefault{ #1 }{ name }{ }
          }
      }
      {
        \property_new:nnnn { keytheorems/recordednote } { now } { }
          { \l__keythms_thmuse_note_tl }
        \cs_new:Npn \__keythms_thmuse_recordnote:
          {
            \clist_clear:N \l__keythms_tmpa_clist
            \tl_if_empty:NF \l__keythms_thmuse_note_tl
              {
                \clist_put_right:Nn \l__keythms_tmpa_clist
                  { keytheorems/recordednote }
              }
            \tl_if_empty:NF \l__keythms_thmuse_shortnote_tl
              {
                \clist_put_right:Nn \l__keythms_tmpa_clist
                  { keytheorems/recordedshortnote }
              }
            \clist_if_empty:NF \l__keythms_tmpa_clist
              {
                \RecordProperties
                  { keythms_recordednote_\l__keythms_thmuse_label_tl }
                  { \l__keythms_tmpa_clist }
              }
          }
        \cs_new:Npn \__keythms_getrecordednote:n #1
          {
            \property_ref:nn { keythms_recordednote_#1 }
              { keytheorems/recordednote }
          }
      }
    \IfFormatAtLeastTF { 2024-06-01 }
      {
        \property_new:nnnn { keytheorems/recordedshortnote } { now } { }
          { \l__keythms_thmuse_shortnote_tl }
        \cs_new:Npn \__keythms_getrecordedshortnote:n #1
          {
            \property_ref:nn { keythms_recordednote_#1 }
              { keytheorems/recordedshortnote }
          }
      }
      { % if format not new enough, just don't support continues* and short-note
        \cs_new:Npn \__keythms_getrecordedshortnote:n #1 { }
        % also need to cancel this definition
        \cs_set:Npn \__keythms_thmuse_recordnote: { }
      }
  }
\hook_gput_code:nnn { begindocument } { . }
  { \tl_use:N \c__keythms_notesetup_tl }

\keys_define:nn { keytheorems/thmuse }
  {
    continues  .tl_set:N = \l__keythms_thmuse_contlabel_tl,
    continues* .code:n   =
      {
        \keys_set:nn { keytheorems/thmuse } { continues = #1 }
        \protected@edef \l__keythms_tmpa_tl
          { \__keythms_getrecordednote:n { #1 } }
        \tl_if_empty:NF \l__keythms_tmpa_tl
          {
            \keys_set:nn { keytheorems/thmuse }
              { note = \l__keythms_tmpa_tl }
          }
      },
    label      .tl_set:N = \l__keythms_thmuse_label_tl,
    listhack   .choice:, % needs equals sign
    listhack / true .code:n = \bool_set_true:N \l__keythms_thmuse_listhack_bool,
    listhack / false .code:n = \bool_set_false:N \l__keythms_thmuse_listhack_bool,
    listhack   .initial:n = false,
    name       .meta:n   = { note = {#1} },
    % ^ for compatibility. "name" is ambiguous and doesn't match amsthm language
    note       .tl_set:N = \l__keythms_thmuse_note_tl,
    note       .initial:n = {},
    manual-num .tl_set:N = \l__keythms_thmuse_manualnum_tl,
    restate    .meta:n   = { store = {#1} }, % thmtools compatibility
    restate*   .meta:n   = { store* = {#1} },
    restate-keys .clist_set:N = \l__keythms_thmuse_restatekeys_clist,
    seq        .code:n   = {},
    short-note .tl_set:N = \l__keythms_thmuse_shortnote_tl,
    short-name .code:n   = {},
    store      .tl_set:N = \l__keythms_thmuse_store_tl, % should this be .tl_set_e:N ?
    store*     .tl_set:N = \l__keythms_thmuse_storereversed_tl,
  }

\keys_precompile:nnN { keytheorems/thmuse }
  { % this is needed in case of nested theorems
    continues={},
    label={},
    listhack=false,
    note={},
    manual-num={},
    short-note={},
    store={},
    store*={},
  }
  \l__keythms_thmuse_defaultkeys_tl

\cs_new_protected:Npn \__keythms_keyify_theorem:n #1
  { % #1 = theorem name
    \DeclareEnvironmentCopy { keythms_orig_#1 } { #1 }
    \DeclareDocumentEnvironment { keythms_grab_#1 } { m m +b }
      { % ##1 = keys, ##2 = note, ##3 = theorem body
        \__keythms_thm_prehead_code:n { #1 }
        \begin{keythms_orig_#1}[{##2}]
        \clist_map_inline:Nn \g__keythms_restatecounters_clist
          {
            \prop_gput:Nne \g__keythms_thmuse_othercounters_prop { ####1 }
              { \the\value{####1} }
          }
        \__keythms_thm_posthead_code:n { #1 }
        % below needs to come after posthead so that correct \@currentHref
        % is stored for tcolorbox theorems
        \__keythms_thm_addcontentsdata:nnnn { #1 }
          { \prop_to_keyval:N \g__keythms_thmuse_othercounters_prop }
          { ##1 } { ##3 }
        \__keythms_thm_tempstorerestatedata:nnn { #1 } { ##1 } { ##3 }
        ##3
        \__keythms_thm_prefoot_code:n { #1 }
        \end{keythms_orig_#1}
        \__keythms_thm_postfoot_code:n { #1 }
      }
      { }
    \DeclareDocumentEnvironment { keythms_grabreversed_#1 } { m m +b }
      { % ##1 = keys, ##2 = note, ##3 = theorem body
        \tl_if_exist:cTF
          { c__keythms_storeatbegin_ \l__keythms_thmuse_storereversed_tl _restatecounters_tl }
          {
            \bool_set_true:N \l__keythms_thmuse_restating_bool
            \prop_set_from_keyval:Ne \l__keythms_restate_counters_prop
              { \tl_use:c { c__keythms_storeatbegin_ \l__keythms_thmuse_storereversed_tl _restatecounters_tl } }
            \prop_map_inline:Nn \l__keythms_restate_counters_prop
              {
                \tl_set:ce { l__keythms_restate_current_####1_tl }
                  { \the\value{####1} }
                \setcounter { ####1 } { ####2 }
                % ^ FIX: what if eq's numbered by section, theorem, etc.? The
                %        thmtools code is opaque.... Or maybe should be up to the
                %        user to say "restate-counters={section,chapter,...}".
                \cs_set:cpn { theH ####1 }
                  { \use:c { the ####1 } . \theHkeythms_restate_dummyctr }
              }
            \tl_if_empty:cTF
              { c__keythms_storeatbegin_ \l__keythms_thmuse_storereversed_tl _label_tl }
              { \refstepcounter{keythms_restate_dummyctr} } % for unnumbered theorems
              {
                \cs_set:cpn { the #1 }
                  { \tl_use:c { c__keythms_storeatbegin_ \l__keythms_thmuse_storereversed_tl _label_tl } }
                \cs_set_eq:cN { c@ #1 } \c@keythms_restate_dummyctr
                \cs_set_eq:cN { theH #1 } \theHkeythms_restate_dummyctr
                % ^ why are the last two lines here? We shouldn't be referencing
                %   restated theorems. Think it's a remnant of thmtools
                % WRONG: needed to make numbering correct after restated theorem.
                % not sure about theH. <- this is needed to prevent duplicate anchors
              }
           }
           {
             \msg_warning:nnV { keytheorems } { store-reversed-not-got }
               \l__keythms_thmuse_storereversed_tl
           }
        \__keythms_thm_prehead_code:n { #1 }
        \hook_use:n { keytheorems/#1/restated }
        \hook_use:n { keytheorems/allthms/restated }
        \begin{keythms_orig_#1}[{##2}]
        \__keythms_thm_posthead_code:n { #1 }
        % below needs to come after posthead so that correct \@currentHref
        % is stored for tcolorbox theorems
        \__keythms_thm_addstoredreverseddata:nnn { #1 } { ##1 } { ##3 }
        \__keythms_thm_tempstorerestatedatareversed:nnn { #1 } { ##1 } { ##3 }
        ##3
        \__keythms_thm_prefoot_code:n { #1 }
        \end{keythms_orig_#1}
        \__keythms_thm_postfoot_code:n { #1 }
        \prop_map_inline:Nn \l__keythms_restate_counters_prop
          {
            \exp_args:Nnc \setcounter { ####1 }
              { l__keythms_restate_current_####1_tl }
          }
      }
      { }
    % NOTE: have to do a lot of shenanigans to make sure the begin/end of grabbed
    %       theorem env captures only the body and no package code.
    %       This is the price of on-the-fly redefining the env to grab body
    \RenewDocumentEnvironment { #1 } { ={note} o }
      {
        \tl_set:Nn \l_keythms_thmuse_envname_tl { #1 }
        \tl_use:N \l__keythms_thmuse_defaultkeys_tl
        \tl_if_novalue:nF { ##1 }
          {
            \keys_set:nn { keytheorems/thmuse } { ##1 }
          }
        \tl_if_empty:NTF \l__keythms_thmuse_store_tl
          {
            \tl_if_empty:NTF \l__keythms_thmuse_storereversed_tl
              {
                \__keythms_thm_prehead_code:n { #1 }
              }
              {
                \bool_gset_true:N \g__keythms_listof_writefile_bool
                \cs_set_eq:NN \__keythms_withhooks_begin:nnn \__keythms_grabreversed_begin:nnn
                \cs_set_eq:NN \__keythms_withhooks_end:n \__keythms_grabreversed_end:n
              }
          }
          {
            \bool_gset_true:N \g__keythms_listof_writefile_bool
            \cs_set_eq:NN \__keythms_withhooks_begin:nnn \__keythms_grab_begin:nnn
            \cs_set_eq:NN \__keythms_withhooks_end:n \__keythms_grab_end:n
          }
        \__keythms_withhooks_begin:nnV { #1 } { ##1 } \l__keythms_thmuse_note_tl
      }
      {
        \__keythms_withhooks_end:n { #1 }
        \tl_if_empty:NF \l__keythms_thmuse_store_tl
          {
            \cs_if_exist:cF
              { __keythms_getthm_ \l__keythms_thmuse_store_tl _theorem }
              {
                \cs_new:cpe
                  { __keythms_getthm_ \l__keythms_thmuse_store_tl _theorem }
                  {
                    \exp_not:N \keythms_getthm_theorem:nnnnn
                    \exp_not:o { \g__keythms_thmuse_temprestatedata_tl }
                  }
                \cs_new:cpe
                  { __keythms_getthm_ \l__keythms_thmuse_store_tl _body }
                  {
                    \exp_not:N \keythms_getthm_body:nnn
                    \exp_args:No \exp_not:o
                      {
                        \exp_after:wN \__keythms_use_i_iii_v_braced:nnnnn
                          \g__keythms_thmuse_temprestatedata_tl
                      }
                  }
              }
          }
        \tl_if_empty:NF \l__keythms_thmuse_storereversed_tl
          {
            \cs_if_exist:cF
              { __keythms_getthm_ \l__keythms_thmuse_storereversed_tl _theorem }
              {
                \cs_new:cpe
                  { __keythms_getthm_ \l__keythms_thmuse_storereversed_tl _theorem }
                  {
                    \exp_not:N \__keythms_getthmreversed_theorem:nnn
                    \exp_not:o { \g__keythms_thmuse_temprestatedatareversed_tl }
                  }
                \cs_new:cpn
                  { __keythms_getthm_ \l__keythms_thmuse_storereversed_tl _body }
                  {
                    \textbf{??}
                    \msg_warning:nnn { keytheorems } { restate-body-never-got }
                      { #1 }
                  }
              }
          }
      }
  }
\cs_new:Npn \__keythms_use_i_iii_v_braced:nnnnn #1#2#3#4#5 { {#1}{#3}{#5} }

% withhooks_begin does not include prehead hook because we want to be able to access note
\cs_new_protected:Npn \__keythms_withhooks_begin:nnn #1#2#3
  { % #1 = theorem name, #2 = keys, #3 = note
    \begin{keythms_orig_#1}[{#3}]
    \__keythms_thm_posthead_code:n { #1 }
    \__keythms_thm_addcontentsdata:nnnn { #1 } { } { #2 } { }
    \ignorespaces % I hope this is alright
  }
\cs_generate_variant:Nn \__keythms_withhooks_begin:nnn { nnV }
\cs_new_protected:Npn \__keythms_withhooks_end:n #1
  {
    \__keythms_thm_prefoot_code:n { #1 }
    \end{keythms_orig_#1}
    \__keythms_thm_postfoot_code:n { #1 }
  }
\cs_new_protected:Npn \__keythms_grab_begin:nnn #1#2#3
  { % #1 = theorem name, #2 = keys, #3 = note
    \begin{keythms_grab_#1}{#2}{#3}
  }
\cs_new_protected:Npn \__keythms_grab_end:n #1 { \end{keythms_grab_#1} }

\cs_new_protected:Npn \__keythms_grabreversed_begin:nnn #1#2#3
  { % #1 = theorem name, #2 = keys, #3 = note
    \begin{keythms_grabreversed_#1}{#2}{#3}
  }
\cs_new_protected:Npn \__keythms_grabreversed_end:n #1
  { \end{keythms_grabreversed_#1} }

\cs_new_protected:Npn \__keythms_orig_begin:nn #1#2
  { \begin{keythms_orig_#1}[{#2}] }
\cs_generate_variant:Nn \__keythms_orig_begin:nn { nV }
\cs_new_protected:Npn \__keythms_orig_end:n #1 { \end{keythms_orig_#1} }

%% this below has to be separate from withhooks_begin above since we need to add
%% continues-code to note before retrieving it in \__keythms_withhooks_begin:nnV
\cs_new_protected:Npn \__keythms_thm_prehead_code:n #1
  { % #1 = theorem name
    \tl_if_empty:NF \l__keythms_thmuse_contlabel_tl
      {
        \tl_if_empty:NF \l__keythms_thmuse_note_tl
          { \tl_put_right:Nn \l__keythms_thmuse_note_tl { , ~ } }
        \tl_put_right:Ne \l__keythms_thmuse_note_tl
          { \__keythms_thmuse_continues:V \l__keythms_thmuse_contlabel_tl }
        \cs_set:cpn { the #1 }
          {
            \getrefnumber { \l__keythms_thmuse_contlabel_tl }
          }
        \cs_set_eq:cN { c@ #1 } \c@keythms_continues_dummyctr
        \cs_set_eq:cN { theH #1 } \theHkeythms_continues_dummyctr
        %\cs_set_eq:NN \setuniqmark \use_none:n % not the right fix
      }
    \tl_if_empty:NF \l__keythms_thmuse_manualnum_tl
      {
        \cs_set:cpn { the #1 }
          { % prevent expansion for unexpandable tokens in \the<counter>
            \exp_not:N \exp_not:n { \l__keythms_thmuse_manualnum_tl }
          }
        \cs_set_eq:cN { c@ #1 } \c@keythms_manualnum_dummyctr
        \cs_set_eq:cN { theH #1 } \theHkeythms_manualnum_dummyctr
      }
    \hook_use:n { keytheorems/#1/prehead }
    \hook_use:n { keytheorems/allthms/prehead }
    % \use:c instead of \tl_use:c so doesn't error if tl doesn't exist
    \use:c { g__keythms_thm_tcbprehead_#1_tl }
  }
\cs_new_protected:Npn \__keythms_thm_posthead_code:n #1
  { % #1 = theorem name
    \hook_use:n { keytheorems/#1/posthead }
    \hook_use:n { keytheorems/allthms/posthead }
    \tl_if_empty:NF \l__keythms_thmuse_label_tl
      {
        \label{ \l__keythms_thmuse_label_tl }
        \__keythms_thmuse_recordnote:
      }
    \bool_if:NT \l__keythms_thmuse_listhack_bool
      { % straight from thm-amsthm.sty
        \leavevmode
        \vspace{-\baselineskip}%
        \par
        \everypar{\setbox\z@\lastbox\everypar{}}%
      }
  }
\cs_new_protected:Npn \__keythms_thm_prefoot_code:n #1
  { % #1 = theorem name
    \use:c { g__keythms_thm_QEDprefoot_#1_tl }
    \hook_use:n { keytheorems/allthms/prefoot }
    \hook_use:n { keytheorems/#1/prefoot }
  }
\cs_new_protected:Npn \__keythms_thm_postfoot_code:n #1
  { % #1 = theorem name
    \use:c { g__keythms_thm_tcbpostfoot_#1_tl }
    \hook_use:n { keytheorems/allthms/postfoot }
    \hook_use:n { keytheorems/#1/postfoot }
  }
\cs_new_protected:Npn \__keythms_thm_addcontentsdata:nnnn #1#2#3#4
  { % #1 = theorem name, #2 = stored counters, #3 = keys, #4 = body
    \keythms_listof_chaptervspacehack:
    \iow_shipout:Ne \@auxout
      {
        \token_to_str:N \@writefile { thlist }
          {
            \token_to_str:N \KeyThmsSavedTheorem { #1 }
              { \@currentlabel }
              { \@currentHref }
              { \thepage }
              { #2 }
              { \tl_if_novalue:nF { #3 } { \exp_not:n { #3 } } }
              { \exp_not:n { #4 } }
          }
      }
  }
\cs_new_protected:Npn \__keythms_thm_addstoredreverseddata:nnn #1#2#3
  { % #1 = theorem name, #2 = keys, #3 = body
    \iow_shipout:Ne \@auxout
      {
        \token_to_str:N \@writefile { thlist }
          {
            \token_to_str:N \KeyThmsSavedTheoremReversed { \l__keythms_thmuse_storereversed_tl }
              { #1 }
              { \exp_not:n { #2 } }
              { \exp_not:n { #3 } }
          }
      }
  }
\cs_new_protected:Npn \__keythms_thm_tempstorerestatedata:nnn #1#2#3
  { % #1 = theorem name, #2 = keys, #3 = body
    \tl_gset:Ne \g__keythms_thmuse_temprestatedata_tl % needs to be global to get out of env
      {
        { #1 }
        { \@currentlabel }
        { \prop_to_keyval:N \g__keythms_thmuse_othercounters_prop }
        { \exp_not:n { #2 } }
        { \exp_not:n { #3 } }
      }
  }
\cs_new_protected:Npn \__keythms_thm_tempstorerestatedatareversed:nnn #1#2#3
  {
    \tl_gset:Ne \g__keythms_thmuse_temprestatedatareversed_tl % needs to be global to get out of env
      {
        { #1 }
        { \exp_not:n { #2 } }
        { \exp_not:n { #3 } }
      }
  }

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Retrieving Theorem Data %%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\cs_new_protected:Npn \__keythms_listof_savedtheorem:nnnnnnn #1#2#3#4#5#6#7 % 7th arg is body
  { \use:c { __keythms_thmitem_#1:nnnnnn } {#2}{#3}{#4}{#5}{#6}{#7} }
\cs_new_eq:NN \KeyThmsSavedTheorem \__keythms_listof_savedtheorem:nnnnnnn
\cs_new_protected:Npn \KeyThmsSavedTheoremReversed #1#2#3#4 { } % gobble by default

\keys_define:nn { keytheorems/storeatbegin }
  {
    restate  .meta:n   = { store = {#1} },
    restate* .meta:n   = { store* = {#1} },
    store    .tl_set:N = \l__keythms_storeatbegin_store_tl,
    store*   .tl_set:N = \l__keythms_storeatbegin_storereversed_tl,
    unknown  .code:n   = {} % do nothing with unknown keys
  }

\cs_new_protected:Npn \KeyThmsContentsLine #1 { }
% ^ initially a no-op, redefined where needed; important it's protected!
\NewDocumentCommand \addtheoremcontentsline { m +m }
  {
    \keythms_listof_chaptervspacehack:
    \addtocontents { thlist }
      {
        \KeyThmsContentsLine
          { % copied from def of \addcontentsline
            \protect\contentsline{#1}{#2}{\thepage}{}
            \protected@file@percent
          }
      }
  }
\NewDocumentCommand \addtotheoremcontents { +m }
  {
    \keythms_listof_chaptervspacehack:
    \addtocontents { thlist }
      {
        \KeyThmsContentsLine { #1 }
      }
  }

\tl_const:Nn \c__keythms_thlistsetup_tl
  {
    \group_begin:
    \cs_set_protected:Npn \KeyThmsSavedTheorem #1#2#3#4#5#6#7
      {
        \group_begin:
        \keys_set:nn { keytheorems/storeatbegin } { #6 }
        \tl_if_empty:NF \l__keythms_storeatbegin_store_tl
          {
            \cs_if_exist:cTF { __keythms_getthm_ \l__keythms_storeatbegin_store_tl _theorem }
              {
                \msg_error:nnV { keytheorems } { stored-tag-taken }
                  \l__keythms_storeatbegin_store_tl
              }
              {
                \cs_new_protected:cpn
                  { __keythms_getthm_ \l__keythms_storeatbegin_store_tl _theorem }
                  {
                    \keythms_getthm_theorem:nnnnn
                      {#1}{#2}{#5}{#6}{#7}
                  }
                \cs_new_protected:cpn
                  { __keythms_getthm_ \l__keythms_storeatbegin_store_tl _body }
                  {
                    \keythms_getthm_body:nnn {#1}{#5}{#7}
                  }
              }
          }
        \tl_if_empty:NF \l__keythms_storeatbegin_storereversed_tl
          {
            \tl_const:cn
              { c__keythms_storeatbegin_ \l__keythms_storeatbegin_storereversed_tl _label_tl }
              { #2 }
            \tl_const:cn
              { c__keythms_storeatbegin_ \l__keythms_storeatbegin_storereversed_tl _restatecounters_tl }
              { #5 }
            \cs_new_protected:cpn
              { __keythms_getthm_ \l__keythms_storeatbegin_storereversed_tl _body }
              {
                \keythms_getthm_body:nnn {#1}{#5}{#7}
              }
          }
        \group_end:
      }
    \cs_set_protected:Npn \KeyThmsSavedTheoremReversed #1#2#3#4
      {
        \bool_new:c { g__keythms_restate_#1_called_bool }
        \cs_if_exist:cTF { __keythms_getthm_#1_theorem }
          {
            \msg_error:nnn { keytheorems } { stored-tag-taken } { #1 }
          }
          {
            \cs_gset:cpn { __keythms_getthm_#1_theorem }
              {
                \__keythms_getthmreversed_theorem:nnn { #2 } { #3 } { #4 }
              }
          }
        \hook_gput_code:nnn { begindocument/end } { . }
          {
            \cs_if_exist:cF { __keythms_getthm_#1_body }
              {
                \cs_new_protected:cpn { __keythms_getthm_#1_body }
                  {
                    \textbf{??}
                    \msg_warning:nnn { keytheorems } { restate-body-never-got } { #1 }
                  }
              }
          }
      }
    \makeatletter % guard against @; \@starttoc already does this
    \file_if_exist_input:n { \c_sys_jobname_str.thlist }
    \group_end:
  }
\hook_gput_code:nnn { begindocument } { . }
  { \tl_use:N \c__keythms_thlistsetup_tl }

\prg_new_conditional:Npnn \keythms_if_restating: { T, F, TF }
  {
    \bool_if:NTF \l__keythms_thmuse_restating_bool
      { \prg_return_true: }
      { \prg_return_false: }
  }
\NewDocumentCommand \IfRestatingTF { } { \keythms_if_restating:TF }
\NewDocumentCommand \IfRestatingT { } { \keythms_if_restating:T }
\NewDocumentCommand \IfRestatingF { } { \keythms_if_restating:F }

\hook_gput_code:nnn { keytheorems/allthms/restated } { . }
  { % code to disable things in restated theorems
    \cs_set_eq:NN \label \@gobble@om % opt arg in case cleveref loaded
    \cs_set_eq:NN \ltx@label \use_none:n % thmtools does this; why?
    \cs_set_eq:NN \property_record:nn \use_none:nn
    \cs_set_eq:NN \setuniqmark \use_none:n % work with numbered=unless-unique
    \cs_set_eq:NN \index \@gobble@som % see ltsect.dtx
    \cs_set_eq:NN \glossary \@gobble@om % see ltsect.dtx 
    % QUESTION: also disable \hyper@@anchor? \MakeLinkTarget?
  }

\cs_new_protected:Npn \keythms_getthm_theorem:nnnnn #1#2#3#4#5
  { % #1 = name, #2 = number, #3 = restate counters, #4 = keys, #5 = theorem body
    \group_begin:
    \bool_set_true:N \l__keythms_thmuse_restating_bool
    \prop_set_from_keyval:Nn \l__keythms_restate_counters_prop { #3 }
    \prop_map_inline:Nn \l__keythms_restate_counters_prop
      {
        \tl_set:ce { l__keythms_restate_current_##1_tl } { \the\value{##1} }
        \setcounter { ##1 } { ##2 }
        % ^ FIX: what if eq's numbered by section, theorem, etc.? The
        %        thmtools code is opaque.... Or maybe should be up to the
        %        user to say "restate-counters={section,chapter,...}".
        \cs_set:cpn { theH ##1 }
          { \use:c { the ##1 } . \theHkeythms_restate_dummyctr }
      }
    \tl_if_empty:nTF { #2 }
      { \refstepcounter{keythms_restate_dummyctr} } % for unnumbered theorems
      {
        \cs_set:cpn { the #1 } { #2 }
        \cs_set_eq:cN { c@ #1 } \c@keythms_restate_dummyctr
        \cs_set_eq:cN { theH #1 } \theHkeythms_restate_dummyctr
        % ^ why are the last two lines here? We shouldn't be referencing
        %   restated theorems. Think it's a remnant of thmtools
        % WRONG: needed to make numbering correct after restated theorem.
        % not sure about theH. <- this is needed to prevent duplicate anchors
      }
    \tl_set:Nn \l_keythms_thmuse_envname_tl { #1 }
    \tl_use:N \l__keythms_thmuse_defaultkeys_tl
    \keys_set:nn { keytheorems/thmuse } { #4 }
    \keys_set:no { keytheorems/thmuse } { \l__keythms_thmuse_restatekeys_clist }
    \__keythms_thm_prehead_code:n { #1 }
    \hook_use:n { keytheorems/#1/restated }
    \hook_use:n { keytheorems/allthms/restated }
    \__keythms_orig_begin:nV { #1 } \l__keythms_thmuse_note_tl
    \__keythms_thm_posthead_code:n { #1 }
    #5
    \__keythms_thm_prefoot_code:n { #1 }
    \__keythms_orig_end:n { #1 }
    \__keythms_thm_postfoot_code:n { #1 }
    \prop_map_inline:Nn \l__keythms_restate_counters_prop
      {
        \exp_args:Nnc \setcounter { ##1 }
          { l__keythms_restate_current_##1_tl }
      }
    \group_end:
  }

\cs_new_protected:Npn \keythms_getthm_body:nnn #1#2#3
  { % #1 = name, #2 = restate counters, #3 = theorem body
    \group_begin:
    \bool_set_true:N \l__keythms_thmuse_restating_bool
    \prop_set_from_keyval:Nn \l__keythms_restate_counters_prop { #2 }
    \prop_map_inline:Nn \l__keythms_restate_counters_prop
      {
        \tl_set:ce { l__keythms_restate_current_##1_tl } { \the\value{##1} }
        \setcounter { ##1 } { ##2 }
        % ^ FIX: what if eq's numbered by section, theorem, etc.? The
        %        thmtools code is opaque.... Or maybe should be up to the
        %        user to say "restate-counters={section,chapter,...}".
        \cs_set:cpn { theH ##1 }
          { \use:c { the ##1 } . \theHkeythms_restate_dummyctr }
      }
    \refstepcounter{keythms_restate_dummyctr}
    \hook_use:n { keytheorems/#1/restated }
    \hook_use:n { keytheorems/allthms/restated }
    #3
    \prop_map_inline:Nn \l__keythms_restate_counters_prop
      {
        \exp_args:Nnc \setcounter { ##1 }
          { l__keythms_restate_current_##1_tl }
      }
    \group_end:
  }

\cs_new_protected:Npn \__keythms_getthmreversed_theorem:nnn #1#2#3
  { % #1 = envname, #2 = keys, #3 = theorem body
    \group_begin:
    \bool_set_false:N \l__keythms_thmuse_restating_bool
    \tl_set:Nn \l_keythms_thmuse_envname_tl { #1 }
    \tl_use:N \l__keythms_thmuse_defaultkeys_tl
    \keys_set:nn { keytheorems/thmuse } { #2 }
    \keys_set:no { keytheorems/thmuse } { \l__keythms_thmuse_restatekeys_clist }
    \__keythms_thm_prehead_code:n { #1 }
    \__keythms_orig_begin:nV { #1 } \l__keythms_thmuse_note_tl
    \clist_map_inline:Nn \g__keythms_restatecounters_clist
      {
        \prop_gput:Nne \g__keythms_thmuse_othercounters_prop { ##1 }
          { \the\value{##1} }
      }
    \__keythms_thm_posthead_code:n { #1 }
    \__keythms_thm_addcontentsdata:nnnn { #1 }
      { \prop_to_keyval:N \g__keythms_thmuse_othercounters_prop }
      { #2 } { #3 }
    \__keythms_thm_tempstorerestatedata:nnn { #1 } { #2 } { #3 } % for defining getthm_body
    #3
    \__keythms_thm_prefoot_code:n { #1 }
    \__keythms_orig_end:n { #1 }
    \__keythms_thm_postfoot_code:n { #1 }
    % While we're here, define getthm_body
    \cs_if_exist:cF
      { __keythms_getthm_ \l__keythms_thmuse_storereversed_tl _body }
      {
        \cs_new:cpe
          { __keythms_getthm_ \l__keythms_thmuse_storereversed_tl _body }
          {
            \exp_not:N \keythms_getthm_body:nnn
            \exp_args:No \exp_not:o
              {
                \exp_after:wN \__keythms_use_i_iii_v_braced:nnnnn
                  \g__keythms_thmuse_temprestatedata_tl
              }
          }
      }
    \bool_gset_true:c
      { g__keythms_restate_ \l__keythms_thmuse_storereversed_tl _called_bool }
    \group_end:
  }

\NewDocumentCommand \getkeytheorem { O{theorem} m }
  { % #1 = property, #2 = tag
    \cs_if_exist:cTF { __keythms_getthm_#2_#1 }
      {
        \bool_if_exist:cTF { g__keythms_restate_#2_called_bool }
          {
            \str_if_eq:nnTF { #1 } { theorem }
              {
                \bool_if:cTF
                  { g__keythms_restate_#2_called_bool }
                  {
                    \msg_error:nnn { keytheorems }
                      { store-reversed-called-twice } { #2 }
                  }
                  { \use:c { __keythms_getthm_#2_#1 } }
              }
              { \use:c { __keythms_getthm_#2_#1 } }
          }
          { \use:c { __keythms_getthm_#2_#1 } }
      }
      {
        \textbf{??}
        \cs_if_exist:cTF { __keythms_getthm_#2_theorem }
          {
            \msg_warning:nnnn { keytheorems } { no-prop-for-stored-theorem }
              { #1 } { #2 } % should this be an error?
          }
          { \msg_warning:nnn { keytheorems } { no-stored-theorem } { #2 } }
      }
  }

\NewDocumentCommand { \externaltheorems } { O{} m }
  {
    \group_begin:
    \cs_set_protected:Npn \KeyThmsSavedTheorem ##1##2##3##4##5##6##7
      {
        \group_begin:
        \keys_set:nn { keytheorems/storeatbegin } { ##6 }
        \tl_if_empty:NF \l__keythms_storeatbegin_store_tl
          {
            \cs_if_exist:cTF
              { __keythms_getthm_ #1 \l__keythms_storeatbegin_store_tl _theorem }
              {
                \msg_error:nne { keytheorems } { stored-tag-taken }
                  { #1 \l__keythms_storeatbegin_store_tl }
              }
              {
                \cs_new_protected:cpn
                  { __keythms_getthm_ #1 \l__keythms_storeatbegin_store_tl _theorem }
                  {
                    \keythms_getthm_theorem:nnnnn
                      {##1}{##2}{##5}{##6}{##7}
                  }
                \cs_new_protected:cpn
                  { __keythms_getthm_ #1 \l__keythms_storeatbegin_store_tl _body }
                  {
                    \keythms_getthm_body:nnn {##1}{##5}{##7}
                  }
              }
          }
        \tl_if_empty:NF \l__keythms_storeatbegin_storereversed_tl
          { % store* should behave just like store in an external document
            \cs_if_exist:cTF
              { __keythms_getthm_ #1 \l__keythms_storeatbegin_storereversed_tl _theorem }
              {
                \msg_error:nne { keytheorems } { stored-tag-taken }
                  { #1 \l__keythms_storeatbegin_storereversed_tl }
              }
              {
                \cs_new_protected:cpn
                  { __keythms_getthm_ #1 \l__keythms_storeatbegin_storereversed_tl _theorem }
                  {
                    \keythms_getthm_theorem:nnnnn
                      {##1}{##2}{##5}{##6}{##7}
                  }
                \cs_new_protected:cpn
                  { __keythms_getthm_ #1 \l__keythms_storeatbegin_storereversed_tl _body }
                  {
                    \keythms_getthm_body:nnn {##1}{##5}{##7}
                  }
              }
          }
        \group_end:
      }
    % ignore \KeyThmsSavedTheoremReversed from external file
    \cs_set_protected:Npn \KeyThmsSavedTheoremReversed ##1##2##3##4 { }
    \makeatletter
    \file_if_exist_input:nF { #2.thlist }
      {
        \msg_warning:nnn { keytheorems } { missing-ext-thlist } { #2 }
      }
    \group_end:
  }

%%%%%%%%%%%%%%%%%%%%%
%%% Theorem Hooks %%%
%%%%%%%%%%%%%%%%%%%%%

\NewDocumentCommand \addtotheoremhook { O{allthms} m +m }
  { % #1 = envname, #2 = hook, #3 = code
    \__hook_if_declared:nTF { keytheorems/allthms/#2 }
      {
        \hook_gput_code:nnn { keytheorems/#1/#2 } { . } { #3 }
      }
      {
        \msg_error:nnn { keytheorems } { undefined-thm-hook } { #2 }
      }
  }
% NOTE: I think it's OK we use the internal \__hook_if_declared:nTF above
%       since we don't need to worry about the user creating new theorem hooks
%       so, as we're only checking the existence of hooks created by us, it's OK.

%%%%%%%%%%%%%%%%%%%%%%%%
%%% List of Theorems %%%
%%%%%%%%%%%%%%%%%%%%%%%%

\keys_define:nn { keytheorems/listof }
  {
    chapter-skip-length .dim_set:N  = \keythms@listof@chaptervspace@dim,
    chapter-skip-length .initial:n  = 10pt,
    chapter-skip-length .value_required:n = true,
    format-code         .cs_set:Np  = \__keythms_listof_misdirect:nnn #1#2#3,
    format-code         .initial:n  = \numberline{#2}#1#3,
    format-code         .value_required:n = true,
    ignore              .code:n     =
      {
        \hook_gput_code:nnn { begindocument } { keytheorems }
          { \keythms_listof_ignore:n { #1 } }
      },
    ignore              .value_required:n = true,
    ignoreall           .code:n     =
      { % in case called before theorem defined
        \hook_gput_code:nnn { begindocument } { keytheorems }
          {
            \prop_map_inline:Nn \g__keythms_thmnames_prop
              { \__keythms_listof_ignore_aux:n { ##1 } }
          }
      },
    ignoreall           .value_forbidden:n = true,
    indent              .dim_set:N  = \l__keythms_listof_indent_dim,
    indent              .initial:n  = 1.5em,
    indent              .value_required:n = true,
    no-chapter-skip     .bool_set:N = \l__keythms_listof_nochapskip_bool,
    no-chapter-skip     .initial:n  = false,
    no-continues        .bool_set:N = \l__keythms_listof_nocont_bool, 
    no-continues        .initial:n  = false,
    no-title            .bool_set:N = \l__keythms_listof_notitle_bool,
    no-title            .initial:n  = false,
    no-toc              .bool_set:N = \l__keythms_listof_notoc_bool,
    no-toc              .initial:n  = false, % false does not mean "to-toc" for standard classes
    note-code           .cs_set:Np  = \__keythms_listof_notecmd:n #1,
    note-code           .initial:n  = { ~ (#1) },
    note-code           .value_required:n = true,
    numwidth            .dim_set:N  = \l__keythms_listof_numwidth_dim,
    numwidth            .initial:n  = 2.3em,
    numwidth            .value_required:n = true,
    one-col             .bool_set:N = \l__keythms_listof_onecol_bool,
    one-col             .initial:n  = false,
    onlynamed           .code:n     =
      {
        \hook_gput_code:nnn { begindocument } { keytheorems }
          { \keythms_listof_onlynamed:n { #1 } }
      },
    onlynamed           .default:n  = \q_no_value,
    onlynumbered        .code:n     =
      {
        \hook_gput_code:nnn { begindocument } { keytheorems }
          { \keythms_listof_onlynumbered:n { #1 } }
      },
    onlynumbered        .default:n  = \q_no_value,
    print-body          .code:n     =
      {
        \cs_set_protected:Nn \keythms_listof_listcmd:nnnnnnn
          {
            \tl_if_empty:nF { ##7 }
              { \keythms_getthm_theorem:nnnnn {##1}{##2}{##5}{##6}{##7} }
          }
      },
    print-body          .value_forbidden:n = true,
    seq                 .code:n     = 
      {
        \hook_gput_code:nnn { begindocument } { keytheorems }
          { \keythms_listof_showseq:n { #1 } }
      },
    show                .code:n     =
      {
        \hook_gput_code:nnn { begindocument } { keytheorems }
          { \keythms_listof_show:n { #1 } }
      },
    show                .value_required:n = true,
    showall             .code:n     =
      { % in case called before theorem defined
        \hook_gput_code:nnn { begindocument } { keytheorems }
          {
            \prop_map_inline:Nn \g__keythms_thmnames_prop
              { \__keythms_listof_show_aux:n { ##1 } }
          }
      },
    showall             .value_forbidden:n = true,
    swapnumber          .bool_set:N = \l__keythms_listof_swapnumber_bool,
    swapnumber          .initial:n  = false,
    title               .tl_set:N   = \l__keythms_listof_title_tl,
    title               .initial:n  = \GetTranslation{keythms_listof_title},
    title               .value_required:n = true,
    title-code          .cs_set:Np  = \__keythms_listof_titlecmd:n #1,
    title-code          .value_required:n = true,
  }

\tl_const:Nn \c__keythms_redeflistkeys_tl
  { % redefine these keys at begindocument/end for reasons above
    \keys_define:nn { keytheorems/listof }
      {
        ignore       .code:n       = \keythms_listof_ignore:n { #1 },
        ignoreall    .code:n       =
          {
            \prop_map_inline:Nn \g__keythms_thmnames_prop
              { \__keythms_listof_ignore_aux:n { ##1 } }
          },
        onlynamed    .code:n       = \keythms_listof_onlynamed:n { #1 },
        onlynamed    .default:n    = \q_no_value,
        onlynumbered .code:n       = \keythms_listof_onlynumbered:n { #1 },
        onlynumbered .default:n    = \q_no_value,
        seq          .code:n       = \keythms_listof_showseq:n { #1 },
        show         .code:n       = \keythms_listof_show:n { #1 },
        showall      .code:n       =
          {
            \prop_map_inline:Nn \g__keythms_thmnames_prop
              { \__keythms_listof_show_aux:n { ##1 } }
          },
      }
  }
\hook_gput_code:nnn { begindocument/end } { . }
  { \tl_use:N \c__keythms_redeflistkeys_tl }

\NewDocumentCommand \keytheoremlistset { +m }
  {
    \keys_set:nn { keytheorems/listof } { #1 }
  }

\cs_new_protected:Npn \keythms_listof_ignore:n #1
  {
    \clist_map_inline:nn { #1 } { \__keythms_listof_ignore_aux:n { ##1 } }
  }
\cs_new_protected:Npn \__keythms_listof_ignore_aux:n #1
  {
    \cs_set_protected:cpn { __keythms_thmitem_#1:nnnnnn } ##1##2##3##4##5##6 { }
  }

\cs_new_protected:Npn \keythms_listof_show:n #1
  {
    \clist_map_inline:nn { #1 } { \__keythms_listof_show_aux:n { ##1 } }
  }
\cs_new_protected:Npn \__keythms_listof_show_aux:n #1
  {
    \cs_set_protected:cpn { __keythms_thmitem_#1:nnnnnn } ##1##2##3##4##5##6
      {
        \__keythms_listof_listcmd_setup:nn { ##5 }
          {
            \keythms_listof_listcmd:nnnnnnn
              {#1}{##1}{##2}{##3}{##4}{##5}{##6}
          }
      }
  }

\cs_new_protected:Npn \keythms_listof_onlynamed:n #1
  {
    \quark_if_no_value:nTF { #1 }
      {
        \prop_map_inline:Nn \g__keythms_thmnames_prop
          { \__keythms_listof_onlynamed_aux:n { ##1 } }
      }
      {
        \clist_map_inline:nn { #1 }
          { \__keythms_listof_onlynamed_aux:n { ##1 } }
      }
  }
\cs_new_protected:Npn \__keythms_listof_onlynamed_aux:n #1
  {
    \cs_set_protected:cpn { __keythms_thmitem_#1:nnnnnn } ##1##2##3##4##5##6
      {
        \__keythms_listof_listcmd_setup:nn { ##5 }
          {
            \tl_if_empty:NF \l__keythms_listofheading_note_tl
              {
                \keythms_listof_listcmd:nnnnnnn
                  {#1}{##1}{##2}{##3}{##4}{##5}{##6}
              }
          }
      }
  }

\cs_new_protected:Npn \keythms_listof_onlynumbered:n #1
  {
    \quark_if_no_value:nTF { #1 }
      {
        \prop_map_inline:Nn \g__keythms_thmnames_prop
          { \__keythms_listof_onlynumbered_aux:n { ##1 } }
      }
      {
        \clist_map_inline:nn { #1 }
          { \__keythms_listof_onlynumbered_aux:n { ##1 } }
      }
  }
\cs_new_protected:Npn \__keythms_listof_onlynumbered_aux:n #1
  {
    \cs_set_protected:cpn { __keythms_thmitem_#1:nnnnnn } ##1##2##3##4##5##6
      {
        \__keythms_listof_listcmd_setup:nn { ##5 }
          {
            \tl_if_empty:nF { ##1 }
              {
                \keythms_listof_listcmd:nnnnnnn
                  {#1}{##1}{##2}{##3}{##4}{##5}{##6}
              }
          }
      }
  }

\cs_new_protected:Npn \keythms_listof_showseq:n #1
  {
    \prop_map_inline:Nn \g__keythms_thmnames_prop
      { \__keythms_listof_showseq_aux:nn { #1 } { ##1 } }
  }
\cs_new_protected:Npn \__keythms_listof_showseq_aux:nn #1#2
  { % #1 = seq name, #2 = theorem name
    \cs_set_protected:cpn { __keythms_thmitem_#2:nnnnnn } ##1##2##3##4##5##6
      {
        \__keythms_listof_listcmd_setup:nn { ##5 }
          {
            \tl_if_eq:NnT \l__keythms_listofheading_seq_tl { #1 }
              {
                \keythms_listof_listcmd:nnnnnnn
                  {#2}{##1}{##2}{##3}{##4}{##5}{##6}
              }
          }
      }
  }
  
% Seems unnecessary to repeat all this for reading the keyvals from file.
% In thmtools they just hook the "thmitem" definition into the theorem declaration.
%% NOTE ON ABOVE: this gives more flexibility to define different kinds of lists.
%% See acro.sty for template idea.
\keys_define:nn { keytheorems/listofheading }
  {
    continues    .tl_set:N    = \l__keythms_listofheading_contlabel_tl,
    continues*   .code:n      =
      {
        \keys_set:nn { keytheorems/listofheading } { continues = #1 }
        \protected@edef \l__keythms_tmpa_tl { \__keythms_getrecordednote:n {#1} }
        \tl_if_empty:NF \l__keythms_tmpa_tl
          {
            \keys_set:nn { keytheorems/listofheading }
              { note = \l__keythms_tmpa_tl }
          }
        \protected@edef \l__keythms_tmpb_tl { \__keythms_getrecordedshortnote:n {#1} }
        \tl_if_empty:NF \l__keythms_tmpb_tl
          {
            \keys_set:nn { keytheorems/listofheading }
              { short-note = \l__keythms_tmpb_tl }
          }
      },
    name         .meta:n      = { note = {#1} },
    note         .tl_set:N    = \l__keythms_listofheading_note_tl,
    restate*     .meta:n      = { store* = {#1} },
    restate-keys .clist_set:N = \l__keythms_listofheading_restatekeys_clist,
    seq          .tl_set:N    = \l__keythms_listofheading_seq_tl,
    short-note   .tl_set:N    = \l__keythms_listofheading_shortnote_tl,
    short-name   .meta:n      = { short-note = {#1} },
    store*       .code:n      =
      {
        \bool_set_true:N \l__keythms_listofheading_storereversed_bool
      },
    unknown      .code:n      = {} % do nothing with unknown keys
  }

\cs_new:Npn \__keythms_listof_printnote:
  {
    \tl_if_empty:NTF \l__keythms_listofheading_shortnote_tl
      {
        \tl_if_empty:NF \l__keythms_listofheading_note_tl
          { \__keythms_listof_notecmd:n { \l__keythms_listofheading_note_tl } }
      }
      {
        \__keythms_listof_notecmd:n { \l__keythms_listofheading_shortnote_tl }
      }
  }

\cs_new:Npn \keythms_listof_listcmd:nnnnnnn #1#2#3#4#5#6#7
  { % #1=name, #2=number, #3=Href, #4=page, #5=restate counters, #6=keys, #7=body
    \contentsline{ #1 }
      {
        \__keythms_listof_misdirect:nnn
          { \prop_item:Nn \g__keythms_thmnames_prop { #1 } }
          { #2 }
          { \__keythms_listof_printnote: }
      }
      { #4 }{ #3 }
  }

\NewDocumentCommand \__keythms_listof_pagerefnolink:w { s m }
  { \getpagerefnumber{#2} } % tagging does not like links within link

% NOTE: We still need to do this setup for [print-body] so that onlynamed works
\cs_new_protected:Npn \__keythms_listof_listcmd_setup:nn #1#2
  { % #1 = keys, #2 = list command
    \group_begin:
    \keys_set:nn { keytheorems/listofheading } { #1 }
    \bool_if:NT \l__keythms_listofheading_storereversed_bool
      {
        \keys_set:no { keytheorems/listofheading }
          { \l__keythms_listofheading_restatekeys_clist }
      }
    \tl_if_empty:NTF \l__keythms_listofheading_contlabel_tl
      { #2 }
      {
        \bool_if:NF \l__keythms_listof_nocont_bool
          {
            \tl_if_empty:NTF \l__keythms_listofheading_shortnote_tl
              {
                \tl_if_empty:NF \l__keythms_listofheading_note_tl
                  {
                    \tl_put_right:Nn \l__keythms_listofheading_note_tl { , ~ }
                  }
                \tl_put_right:Nn \l__keythms_listofheading_note_tl
                  {
                    \__keythms_thmuse_continues:V
                      \l__keythms_listofheading_contlabel_tl
                  }
              }
              {
                \tl_put_right:Nn \l__keythms_listofheading_shortnote_tl
                  {
                    , ~
                    \__keythms_thmuse_continues:V
                      \l__keythms_listofheading_contlabel_tl
                  }
              }
            \cs_set_eq:NN \pageref \__keythms_listof_pagerefnolink:w % always no link
            #2
          }
      }
    \group_end:
  }

\cs_if_exist:NTF \chapter
  { \cs_set_protected:Npn \__keythms_listof_titlecmd:n #1 { \chapter*{#1} } }
  { \cs_set_protected:Npn \__keythms_listof_titlecmd:n #1 { \section*{#1} } }

\cs_new_protected:Npn \__keythms_listof_default_tocline:
   {
     \@dottedtocline{ 1 }{ \l__keythms_listof_indent_dim }
       { \l__keythms_listof_numwidth_dim }
   }
\cs_new_eq:NN \keythms_listof_tocline: \__keythms_listof_default_tocline:

\cs_new_protected:Npn \__keythms_listof_twocolreset: { } % empty by default
\NewDocumentCommand \listofkeytheorems { +O{} }
  {
    \bool_gset_true:N \g__keythms_listof_writefile_bool
    \group_begin:
    \keys_set:nn { keytheorems/listof } { #1 }
    \cs_set_protected:Npn \KeyThmsContentsLine ##1 { ##1 }
    \bool_if:NF \l__keythms_listof_nochapskip_bool
      {
        \cs_set_protected:Npn \KeyThmsAddvspace { \addvspace }
      }
    \bool_if:NT \l__keythms_listof_onecol_bool
      { % actually check if setting \onecolumn is necessary
        \legacy_if:nT { @twocolumn }
          {
            \onecolumn
            \cs_set_protected:Npn \__keythms_listof_twocolreset: { \twocolumn }
          }
      }
    \bool_if:NF \l__keythms_listof_notitle_bool
      {
        \__keythms_listof_titlecmd:n { \l__keythms_listof_title_tl }
        \@mkboth % QUESTION: should this go in titlecmd ?
          { \MakeUppercase \l__keythms_listof_title_tl }
          { \MakeUppercase \l__keythms_listof_title_tl }
      }
    \bool_if:NT \l__keythms_listof_swapnumber_bool
      {
        \cs_set:Npn \__keythms_listof_misdirect:nnn ##1##2##3 { ##1 ~ ##2##3 }
      }
    \legacy_if_set_false:n { @filesw }
    \@starttoc{ thlist }
    \__keythms_listof_twocolreset:
    \group_end:
  }
% ^ unlike thmtools we don't use the class's style of \listoffigures because
%   we want control over title-code, no-title, etc. But this means we have to guess
%   things like marks, sectioning command, etc.

\tl_const:Nn \c__keythms_openthlist_tl
  {
    \bool_if:NTF \g__keythms_listof_writefile_bool
      {
        \legacy_if:nT { @filesw }
          {
            \iow_new:N \tf@thlist
            \iow_open:Nn \tf@thlist { \c_sys_jobname_str.thlist }
          }
      }
      { % if .thlist file left over from previous run but not needed, clear it
        \file_if_exist:nT { \c_sys_jobname_str.thlist }
          {
            \iow_open:Nn \g__keythms_tmpa_iow { \c_sys_jobname_str.thlist }
            \iow_close:N \g__keythms_tmpa_iow
          }
      }
  }
\hook_gput_code:nnn { enddocument } { . }
  { \tl_use:N \c__keythms_openthlist_tl }

% chaptervspacehack (code translated from thmtools)
\cs_new_protected:Npn \KeyThmsAddvspace #1 { } % initially no-op, redefined where needed
% We need to not add space immediately after the title-code, but do add space
% after theorem entries that come before the first chapter. How to detect that?
% Answer: only set prevchapter int at the first theorem
\int_new:N \g_keythms_listof_prevchapter_int
\cs_new_protected:Npn \keythms_listof_chaptervspacehack: { }
\cs_if_exist:cT { c@chapter }
  {
    \hook_gput_next_code:nn { keytheorems/allthms/prehead }
      {
        \int_gset:Nn \g_keythms_listof_prevchapter_int { \value{chapter} }
      }
    \cs_set_protected:Npn \keythms_listof_chaptervspacehack:
      {
        \int_compare:nNnF
          { \value{chapter} } = { \g_keythms_listof_prevchapter_int }
          {
            \addtocontents{ thlist }
              {
                \KeyThmsAddvspace
                  { \keythms@listof@chaptervspace@dim }
              }
            \int_gset:Nn \g_keythms_listof_prevchapter_int { \value{chapter} }
          }
      }
  }

%%%%%%%%%%%%%%%%
%%% \Autoref %%%
%%%%%%%%%%%%%%%%

\DeclareDocumentCommand { \Autoref } { s m }
  {
    \IfPackageLoadedTF { hyperref }
      {
        \group_begin:
        \cs_set_eq:NN \HyRef@testreftype \__keythms_Autoref_testreftype:w
        \IfBooleanTF { #1 } { \autoref*{#2} } { \autoref{#2} }
        \group_end:
      }
      { \msg_error:nn { keytheorems } { hyperref-Autoref } }
  }

\cs_new_protected:Npn \__keythms_Autoref_testreftype:w #1.#2\\
  {
    \cs_if_exist:cTF { #1 Autorefname }
      {
        \cs_set:Npe \HyRef@currentHtag
          {
            \exp_not:N \use:c { #1 Autorefname }
            \exp_not:N \c_space_token
          }
      }
      { \msg_warning:nnn { keytheorems } { no-Autorefname } { #1 } }
  }

%%%%%%%%%%%%%%%%%%%
%%% Global Keys %%%
%%%%%%%%%%%%%%%%%%%

\keys_define:nn { keytheorems }
  {
    auto-translate    .bool_gset:N         = \g__keythms_autotranslate_bool,
    auto-translate    .initial:n           = true,
    auto-translate    .usage:n             = preamble,
    continues-code    .cs_set:Np           = \__keythms_thmuse_continues:n #1,
    continues-code    .initial:n           =
      { % not sure how best to handle this translation
        \GetTranslation{keythms_continues}\pageref{#1}
      },
    continues-code    .value_required:n    = true,
    overload          .code:n              = \tl_use:N \c__keythms_overload_tl,
    overload          .value_forbidden:n   = true,
    overload          .usage:n             = preamble,
    predefined        .code:n              =
      {
        \bool_gset_true:N \g__keythms_predefined_bool
        \keys_set:nn { keytheorems/predefined } { #1 }
      },
    predefined        .default:n           = { },
    predefined        .usage:n             = preamble,
    qed-symbol        .cs_set_protected:Np = \qedsymbol,
    qed-symbol        .value_required:n    = true,
    restate-counters  .code:n              =
      {
        \clist_map_inline:nn { #1 }
          { \tl_new:c { l__keythms_restate_current_##1_tl } }
        \clist_gput_right:Nn \g__keythms_restatecounters_clist { #1 }
      },
    restate-counters  .initial:n           = equation,
    restate-counters  .value_required:n    = true,
    store-all         .code:n              = \__keythms_storeall_code:,
    store-all         .value_forbidden:n   = true,
    store-all         .usage:n             = preamble,
    store-sets-label  .code:n              =
      {
        \keys_define:nn { keytheorems/thmuse }
          {
            store  .code:n =
              {
                \tl_set:Nn \l__keythms_thmuse_label_tl { ##1 }
                \tl_set:Nn \l__keythms_thmuse_store_tl { ##1 }
              },
            store* .code:n =
              {
                \tl_set:Nn \l__keythms_thmuse_label_tl { ##1 }
                \tl_set:Nn \l__keythms_thmuse_storereversed_tl { ##1 }
              },
          }
      },
    thmtools-compat   .code:n              =
      { % prevent loading the code again if key called twice
        \bool_if:NF \g__keythms_thmtoolscompat_bool
          { \tl_use:N \c__keythms_thmtoolscompat_tl }
      },
    thmtools-compat   .value_forbidden:n   = true,
    thmtools-compat   .usage:n             = preamble,
  }

\cs_generate_variant:Nn \__keythms_thmuse_continues:n { V }

\NewDocumentCommand \keytheoremset { +m }
  { % #1 = keys
    \keys_set:nn { keytheorems } { #1 }
  }

\tl_const:Nn \c__keythms_overload_tl
  {
    \RenewDocumentCommand { \newtheorem } { s m o m o }
      {
        \IfBooleanTF { #1 }
          { \keythms_thm_newkeythm:nn { #2 } { name=#4, numbered=false } }
          {
            \IfNoValueTF { #3 }
              {
                \IfNoValueTF { #5 }
                  { \keythms_thm_newkeythm:nn { #2 } { name=#4 } }
                  { \keythms_thm_newkeythm:nn { #2 } { name=#4, parent=#5 } }
              }
              { \keythms_thm_newkeythm:nn { #2 } { name=#4, sibling=#3 } }
          }
      }
  }

\tl_const:Nn \c__keythms_thmtoolscompat_tl
  {
    \bool_gset_true:N \g__keythms_thmtoolscompat_bool
    \tl_use:N \c__keythms_overload_tl % since thmtools overwrites \newtheorem
    \ProvideDocumentCommand { \declaretheoremstyle } { +O{} m }
      {
        \declarekeytheoremstyle { #2 } { #1 }
      }
    \ProvideDocumentCommand { \declaretheorem } { +O{} m }
      {
        \newkeytheorem { #2 } [ #1 ]
      }
    \ProvideDocumentEnvironment { restatable } { ={note} o m m }
      {
        \tl_if_novalue:nTF { #1 }
          {
            \begin{#2}[store=#3]
          }
          {
            \begin{#2}[#1,store=#3]
          }
      }
      {
        \end{#2}
        \cs_new_protected:cpn { #3 }
          { % make \foo and \foo* identical
            \peek_meaning_remove:NTF *
              { \getkeytheorem{ #3 } }
              { \getkeytheorem{ #3 } }
          }
      }
    \ProvideDocumentEnvironment { restatable* } { ={note} o m m }
      {
        \tl_if_novalue:nTF { #1 }
          {
            \begin{#2}[store*=#3]
          }
          {
            \begin{#2}[#1,store*=#3]
          }
      }
      {
        \end{#2}
        \cs_new_protected:cpn { #3 }
          { % make \foo and \foo* identical
            \peek_meaning_remove:NTF *
              { \getkeytheorem{ #3 } }
              { \getkeytheorem{ #3 } }
          }
      }
    \ProvideDocumentCommand { \listoftheorems } { } { \listofkeytheorems }
    \ProvideDocumentCommand { \listtheoremname } { }
      { \GetTranslation{keythms_listof_title} }
    \keys_define:nn { keytheorems/listof }
      { % redefine since thmtools way is \renewcommand\listtheoremname{...}
        title .initial:n = \listtheoremname
      }
    \ProvideDocumentCommand { \addtotheorempreheadhook } { O{allthms} +m }
      {
        \addtotheoremhook [ #1 ] { prehead } { #2 }
      }
    \ProvideDocumentCommand { \addtotheorempostheadhook } { O{allthms} +m }
      {
        \addtotheoremhook [ #1 ] { posthead } { #2 }
      }
    \ProvideDocumentCommand { \addtotheoremprefoothook } { O{allthms} +m }
      {
        \addtotheoremhook [ #1 ] { prefoot } { #2 }
      }
    \ProvideDocumentCommand { \addtotheorempostfoothook } { O{allthms} +m }
      {
        \addtotheoremhook [ #1 ] { postfoot } { #2 }
      }
    \clist_new:N \l__keythms_tcbshaded_keys_clist
    \clist_new:N \l__keythms_tcbthmbox_keys_clist
    \keys_define:nn { keytheorems/thm/shaded }
      {
        textwidth   .code:n =
          \clist_put_right:Nn \l__keythms_tcbshaded_keys_clist { width=#1 },
        textwidth   .value_required:n = true,
        bgcolor     .code:n =
          \clist_put_right:Nn \l__keythms_tcbshaded_keys_clist { colback=#1 },
        bgcolor     .value_required:n = true,
        rulewidth   .code:n =
          \clist_put_right:Nn \l__keythms_tcbshaded_keys_clist { boxrule=#1 },
        rulewidth   .value_required:n = true,
        rulecolor   .code:n =
          \clist_put_right:Nn \l__keythms_tcbshaded_keys_clist { colframe=#1 },
        rulecolor   .value_required:n = true,
        margin      .code:n =
          \clist_put_right:Nn \l__keythms_tcbshaded_keys_clist { boxsep=#1 },
        margin      .value_required:n = true,
        padding     .meta:n = { margin=#1 },
        padding     .value_required:n = true,
        leftmargin  .code:n =
          \clist_put_right:Nn \l__keythms_tcbshaded_keys_clist { left~skip=#1 },
        leftmargin  .value_required:n = true,
        rightmargin .code:n =
          \clist_put_right:Nn \l__keythms_tcbshaded_keys_clist { right~skip=#1 },
        rightmargin .value_required:n = true,
      }
    \keys_define:nn { keytheorems/thm/thmbox }
      {
        L .code:n =
          {
            \clist_put_right:Nn \l__keythms_tcbthmbox_keys_clist
              { keythms_tcbthmbox_L }
          },
        L .value_forbidden:n = true,
        M .code:n =
          {
            \clist_put_right:Nn \l__keythms_tcbthmbox_keys_clist
              { keythms_tcbthmbox_M }
          },
        M .value_forbidden:n = true,
        S .code:n =
          {
            \clist_put_right:Nn \l__keythms_tcbthmbox_keys_clist
              { keythms_tcbthmbox_S }
          },
        S .value_forbidden:n = true,
        underline .choice:,
        underline / true .code:n = {},
        underline / false .code:n =
          {
            \clist_put_right:Nn \l__keythms_tcbthmbox_keys_clist
              { boxed~title~style={bottomrule=0pt} }
          },
        underline .default:n = true,
        nounderline .meta:n = { underline=false },
        nounderline .value_forbidden:n = true,
        cut .choice:,
        cut / true .code:n = {},
        cut / false .code:n =
          {
            \clist_put_right:Nn \l__keythms_tcbthmbox_keys_clist { unbreakable }
          },
        cut .default:n = true,
        nocut .meta:n = { cut=false },
        nocut .value_forbidden:n = true,
        thickness .code:n =
          { % could also add keys to clist with changed dimens; which is better?
            \tl_gput_right:cn { g__keythms_thm_preheadfromkeys_ \l__keythms_thm_envname_tl _tl }
              { \dim_set:Nn \l_keythms_tcbthmbox_thickness_dim { #1 } }
          },
        thickness .value_required:n = true,
        leftmargin .code:n =
          {
            \tl_gput_right:cn { g__keythms_thm_preheadfromkeys_ \l__keythms_thm_envname_tl _tl }
              { \dim_set:Nn \l_keythms_tcbthmbox_leftmargin_dim { #1 } }
          },
        leftmargin .value_required:n = true,
        rightmargin .code:n =
          {
            \tl_gput_right:cn { g__keythms_thm_preheadfromkeys_ \l__keythms_thm_envname_tl _tl }
              { \dim_set:Nn \l_keythms_tcbthmbox_rightmargin_dim { #1 } }
          },
        rightmargin .value_required:n = true,
        hskip .code:n =
          {
            \tl_gput_right:cn { g__keythms_thm_preheadfromkeys_ \l__keythms_thm_envname_tl _tl }
              { \dim_set:Nn \l_keythms_tcbthmbox_hskip_dim { #1 } }
          },
        hskip .value_required:n = true,
        vskip .code:n =
          {
            \tl_gput_right:cn { g__keythms_thm_preheadfromkeys_ \l__keythms_thm_envname_tl _tl }
              { \dim_set:Nn \l_keythms_tcbthmbox_vskip_dim { #1 } }
          },
        vskip .value_required:n = true,
      }
    \dim_new:N \l_keythms_tcbthmbox_thickness_dim
    \dim_set:Nn \l_keythms_tcbthmbox_thickness_dim { 0.6pt }
    \dim_new:N \l_keythms_tcbthmbox_leftmargin_dim
    \dim_set:Nn \l_keythms_tcbthmbox_leftmargin_dim { 0.7\parindent } % use \parindent? thmbox does
    \dim_new:N \l_keythms_tcbthmbox_rightmargin_dim
    \dim_set:Nn \l_keythms_tcbthmbox_rightmargin_dim { 0pt }
    \dim_new:N \l_keythms_tcbthmbox_hskip_dim
    \dim_set:Nn \l_keythms_tcbthmbox_hskip_dim { 0.2em }
    \dim_new:N \l_keythms_tcbthmbox_vskip_dim
    \dim_set:Nn \l_keythms_tcbthmbox_vskip_dim { 0.2em }
    \msg_new:nnn { keytheorems } { mdframed-undefined }
      {
        keytheorems~does~not~define~the~'mdframed'~key.~
        Consider~using~the~'tcolorbox'~key~instead.
      }
    \keys_define:nn { keytheorems/thm }
      {
        shaded .code:n =
          {
            \clist_clear:N \l__keythms_tcbshaded_keys_clist
            \keys_set:nn { keytheorems/thm/shaded } { #1 }
            % FIX: surely a better way to do this
            \RequirePackage{tcolorbox}
            \pgfkeysifdefined{/tcb/keythms_tcbshaded_default/.@cmd} % even worth it?
              { }
              {
                \tcbset % wish I could do this outside of key but can't assume tcb loaded
                  {
                    keythms_tcbshaded_default/.style=
                      {
                        sharp~corners = all,
                        boxrule = 0pt,
                        left = 0pt, right = 0pt,
                        top = 0pt, bottom = 0pt,
                        parbox = false,
                      }
                  }
              }
            \keys_set:ne { keytheorems/thm }
              {
                tcolorbox-no-titlebar =
                  {
                    keythms_tcbshaded_default,
                    \l__keythms_tcbshaded_keys_clist
                  }
              }
          },
        thmbox .code:n = % adapted from https://tex.stackexchange.com/a/236230/208544
          {
            \clist_clear:N \l__keythms_tcbthmbox_keys_clist
            \keys_set:nn { keytheorems/thm/thmbox } { #1 }
            % FIX: surely a better way to do this
            \RequirePackage{tcolorbox}
            \tcbuselibrary{skins,breakable}
            \pgfkeysifdefined{/tcb/keythms_tcbthmbox_default/.@cmd} % even worth it?
              { }
              {
                \tcbset{
                  keythms_tcbthmbox_default/.style={
                    enhanced,
                    breakable,
                    sharp~corners=all,
                    right=\l_keythms_tcbthmbox_hskip_dim,
                    left=\l_keythms_tcbthmbox_hskip_dim,
                    top=\l_keythms_tcbthmbox_vskip_dim,
                    bottom=\l_keythms_tcbthmbox_vskip_dim,
                    coltitle=black,
                    frame~engine=empty,
                    interior~titled~engine=empty,
                    interior~engine=empty,
                    extras~broken={
                      frame~engine=empty,
                      interior~titled~engine=empty,
                      interior~engine=empty
                      },
                    parbox=false,
                    % even though frame isn't drawn, makes spacing correct
                    boxrule=0.5\l_keythms_tcbthmbox_thickness_dim,
                    attach~boxed~title~to~top~left={
                      xshift=-\l_keythms_tcbthmbox_leftmargin_dim,
                      },
                    boxed~title~style={
                      empty,
                      size=minimal,
                      bottom=0.3ex,
                      top=0ex,
                      % ditto
                      bottomrule=0.5\l_keythms_tcbthmbox_thickness_dim,
                      },
                    left~skip=\l_keythms_tcbthmbox_leftmargin_dim,
                    right~skip=\l_keythms_tcbthmbox_rightmargin_dim,
                    overlay~unbroken={
                      \draw[line~width=\l_keythms_tcbthmbox_thickness_dim]
                        (title.south~west)
                        --
                        (title.south~east);
                      \draw[line~width=\l_keythms_tcbthmbox_thickness_dim]
                        (frame.north~west)
                        |-
                        ([xshift=10mm]frame.south~west);
                      },
                    overlay~first={
                      \draw[line~width=\l_keythms_tcbthmbox_thickness_dim]
                        (title.south~west)
                        --
                        (title.south~east);
                      \draw[line~width=\l_keythms_tcbthmbox_thickness_dim]
                        (frame.north~west)
                        --
                        (frame.south~west);
                      },
                    overlay~middle={
                      \draw[line~width=\l_keythms_tcbthmbox_thickness_dim]
                        (frame.north~west)
                        --
                        (frame.south~west);
                      },
                    overlay~last={
                      \draw[line~width=\l_keythms_tcbthmbox_thickness_dim]
                        (frame.north~west)
                        |-
                        ([xshift=10mm]frame.south~west);
                      }
                    },
                  keythms_tcbthmbox_L/.style={
                    overlay~unbroken={
                      \draw[line~width=\l_keythms_tcbthmbox_thickness_dim]
                        (title.south~west)
                        --
                        (title.south~east);
                      \draw[line~width=\l_keythms_tcbthmbox_thickness_dim]
                        (frame.north~west)
                        |-
                        (frame.south~east)
                        -|
                        (frame.north~east);
                      },
                    overlay~first={
                      \draw[line~width=\l_keythms_tcbthmbox_thickness_dim]
                        (title.south~west)
                        --
                        (title.south~east);
                      \draw[line~width=\l_keythms_tcbthmbox_thickness_dim]
                        (frame.north~west)
                        --
                        (frame.south~west);
                      \draw[line~width=\l_keythms_tcbthmbox_thickness_dim]
                        (frame.north~east)
                        --
                        (frame.south~east);
                      },
                    overlay~middle={
                      \draw[line~width=\l_keythms_tcbthmbox_thickness_dim]
                        (frame.north~west)
                        --
                        (frame.south~west);
                      \draw[line~width=\l_keythms_tcbthmbox_thickness_dim]
                        (frame.north~east)
                        --
                        (frame.south~east);
                      },
                    overlay~last={
                      \draw[line~width=\l_keythms_tcbthmbox_thickness_dim]
                        (frame.north~west)
                        |-
                        (frame.south~east)
                        -|
                        (frame.north~east);
                      }
                    },
                  keythms_tcbthmbox_M/.style={},
                  keythms_tcbthmbox_S/.style={ % first and middle same as M
                    overlay~unbroken={
                      \draw[line~width=\l_keythms_tcbthmbox_thickness_dim]
                        (title.south~west)
                        --
                        (title.south~east);
                      \draw[line~width=\l_keythms_tcbthmbox_thickness_dim]
                        (frame.north~west)
                        --
                        (frame.south~west);
                      },
                    overlay~last={
                      \draw[line~width=\l_keythms_tcbthmbox_thickness_dim]
                        (frame.north~west)
                        --
                        (frame.south~west);
                      }
                    },
                  }
              }
            \keys_set:ne { keytheorems/thm }
              {
                tcolorbox =
                  {
                    keythms_tcbthmbox_default,
                    \l__keythms_tcbthmbox_keys_clist
                  }
              }
          },
        thmbox .default:n = M,
        mdframed .code:n = \msg_error:nn { keytheorems } { mdframed-undefined },
      }
    \keys_define:nn { keytheorems/thmstyle }
      {
        shaded   .code:n = \__keythms_thmstyle_savethmkey_optval:n { #1 },
        thmbox   .code:n = \__keythms_thmstyle_savethmkey_optval:n { #1 },
        mdframed .code:n = \msg_error:nn { keytheorems } { mdframed-undefined },
      }
  }

\cs_new_protected:Npn \__keythms_storeall_code:
  {
    \cs_set_eq:NN \__keythms_withhooks_begin:nnn \__keythms_grab_begin:nnn
    \cs_set_eq:NN \__keythms_withhooks_end:n \__keythms_grab_end:n
  }

\tl_const:Nn \c__keythms_translationsetup_tl
  { % use 'provide' in case user defines their own translation in preamble
    \ProvideTranslationFallback { keythms_listof_title } { List~of~Theorems }
    \ProvideTranslationFallback { keythms_continues }    { continuing~from~p.\, }
    \ProvideTranslationFallback { keythms_axiom }        { Axiom }
    \ProvideTranslationFallback { keythms_conjecture }   { Conjecture }
    \ProvideTranslationFallback { keythms_corollary }    { Corollary }
    \ProvideTranslationFallback { keythms_definition }   { Definition }
    \ProvideTranslationFallback { keythms_example }      { Example }
    \ProvideTranslationFallback { keythms_lemma }        { Lemma }
    \ProvideTranslationFallback { keythms_proposition }  { Proposition }
    \ProvideTranslationFallback { keythms_remark }       { Remark }
    \ProvideTranslationFallback { keythms_theorem }      { Theorem }
    \bool_if:NT \g__keythms_autotranslate_bool
      {
        \ProvideTranslation { English }    { keythms_listof_title } { List~of~Theorems }
        \ProvideTranslation { English }    { keythms_continues }    { continuing~from~p.\, }
        \ProvideTranslation { English }    { keythms_axiom }        { Axiom }
        \ProvideTranslation { English }    { keythms_conjecture }   { Conjecture }
        \ProvideTranslation { English }    { keythms_corollary }    { Corollary }
        \ProvideTranslation { English }    { keythms_definition }   { Definition }
        \ProvideTranslation { English }    { keythms_example }      { Example }
        \ProvideTranslation { English }    { keythms_lemma }        { Lemma }
        \ProvideTranslation { English }    { keythms_proposition }  { Proposition }
        \ProvideTranslation { English }    { keythms_remark }       { Remark }
        \ProvideTranslation { English }    { keythms_theorem }      { Theorem }
        % from DeepL; I don't know these languages!
        \ProvideTranslation { Albanian }   { keythms_listof_title } { Lista~e~teoremave }
        \ProvideTranslation { Bulgarian }  { keythms_listof_title } { Списък~на~теоремите }
        \ProvideTranslation { Czech }      { keythms_listof_title } { Seznam~teorémů }
        \ProvideTranslation { Czech }      { keythms_continues }    { pokračování~ze~strany~ }
        \ProvideTranslation { Croatian }   { keythms_listof_title } { Popis~teorema }
        \ProvideTranslation { Croatian }   { keythms_continues }    { nastavak~od~stranice~ }
        \ProvideTranslation { Danish }     { keythms_listof_title } { Liste~over~sætninger }
        \ProvideTranslation { Danish }     { keythms_continues }    { fortsætter~fra~side~ }
        \ProvideTranslation { Danish }     { keythms_axiom }        { Aksiom  }
        \ProvideTranslation { Danish }     { keythms_conjecture }   { Formodning }
        \ProvideTranslation { Danish }     { keythms_corollary }    { Følgeslutning }
        \ProvideTranslation { Danish }     { keythms_definition }   { Definition }
        \ProvideTranslation { Danish }     { keythms_example }      { Eksempel }
        \ProvideTranslation { Danish }     { keythms_lemma }        { Lemma }
        \ProvideTranslation { Danish }     { keythms_proposition }  { Udsagn }
        \ProvideTranslation { Danish }     { keythms_remark }       { Bemærkning }
        \ProvideTranslation { Danish }     { keythms_theorem }      { Teorem }
        \ProvideTranslation { Dutch }      { keythms_listof_title } { Liste~over~sætninger }
        \ProvideTranslation { Dutch }      { keythms_continues }    { fortsætter~fra~side~ }
        \ProvideTranslation { Dutch }      { keythms_axiom }        { Axioma }
        \ProvideTranslation { Dutch }      { keythms_conjecture }   { Conjectuur }
        \ProvideTranslation { Dutch }      { keythms_corollary }    { Gevolg }
        \ProvideTranslation { Dutch }      { keythms_definition }   { Definitie }
        \ProvideTranslation { Dutch }      { keythms_example }      { Voorbeeld }
        \ProvideTranslation { Dutch }      { keythms_lemma }        { Lemma }
        \ProvideTranslation { Dutch }      { keythms_proposition }  { Propositie }
        \ProvideTranslation { Dutch }      { keythms_remark }       { Opmerking }
        \ProvideTranslation { Dutch }      { keythms_theorem }      { Stelling }
        \ProvideTranslation { Estonian }   { keythms_listof_title } { Teoreemide~loetelu }
        \ProvideTranslation { Estonian }   { keythms_continues }    { jätkub~leheküljelt~ }
        \ProvideTranslation { Finnish }    { keythms_listof_title } { Luettelo~teoreemoista }
        \ProvideTranslation { Finnish }    { keythms_continues }    { jatkuu~sivulta~ }
        \ProvideTranslation { French }     { keythms_listof_title } { Liste~des~théorèmes }
        \ProvideTranslation { French }     { keythms_continues }    { suite~de~la~p.\, }
        \ProvideTranslation { French }     { keythms_axiom }        { Axiome }
        \ProvideTranslation { French }     { keythms_conjecture }   { Conjecture }
        \ProvideTranslation { French }     { keythms_corollary }    { Corollaire }
        \ProvideTranslation { French }     { keythms_definition }   { Définition }
        \ProvideTranslation { French }     { keythms_example }      { Exemple }
        \ProvideTranslation { French }     { keythms_lemma }        { Lemme }
        \ProvideTranslation { French }     { keythms_proposition }  { Proposition }
        \ProvideTranslation { French }     { keythms_remark }       { Remarque }
        \ProvideTranslation { French }     { keythms_theorem }      { Théorème }
        \ProvideTranslation { German }     { keythms_listof_title } { Liste~der~Theoreme }
        \ProvideTranslation { German }     { keythms_continues }    { weiter~von~Seite~ }
        \ProvideTranslation { German }     { keythms_axiom }        { Axiom }
        \ProvideTranslation { German }     { keythms_conjecture }   { Vermutung }
        \ProvideTranslation { German }     { keythms_corollary }    { Korollar }
        \ProvideTranslation { German }     { keythms_definition }   { Definition }
        \ProvideTranslation { German }     { keythms_example }      { Beispiel }
        \ProvideTranslation { German }     { keythms_lemma }        { Lemma }
        \ProvideTranslation { German }     { keythms_proposition }  { Satz }
        \ProvideTranslation { German }     { keythms_remark }       { Bemerkung }
        \ProvideTranslation { German }     { keythms_theorem }      { Theorem }
        \ProvideTranslation { Greek }      { keythms_listof_title } { Κατάλογος~θεωρημάτων }
        \ProvideTranslation { Hungarian }  { keythms_listof_title } { A~tételek~listája }
        \ProvideTranslation { Icelandic }  { keythms_listof_title } { Listi~yfir~setningar }
        \ProvideTranslation { Indonesian } { keythms_listof_title } { Daftar~Teorema }
        \ProvideTranslation { Italian }    { keythms_listof_title } { Elenco~dei~teoremi }
        \ProvideTranslation { Italian }    { keythms_continues }    { continua~da~p.\, }
        \ProvideTranslation { Italian }    { keythms_axiom }        { Assioma }
        \ProvideTranslation { Italian }    { keythms_conjecture }   { Congettura }
        \ProvideTranslation { Italian }    { keythms_corollary }    { Corollario }
        \ProvideTranslation { Italian }    { keythms_definition }   { Definizione }
        \ProvideTranslation { Italian }    { keythms_example }      { Esempio }
        \ProvideTranslation { Italian }    { keythms_lemma }        { Lemma }
        \ProvideTranslation { Italian }    { keythms_proposition }  { Proposizione }
        \ProvideTranslation { Italian }    { keythms_remark }       { Osservazione }
        \ProvideTranslation { Italian }    { keythms_theorem }      { Teorema }
        \ProvideTranslation { Latvian }    { keythms_listof_title } { Teorēmu~saraksts }
        \ProvideTranslation { Lithuanian } { keythms_listof_title } { Teoremų~sąrašas }
        \ProvideTranslation { Macedonian } { keythms_listof_title } { Список~на~теореми }
        \ProvideTranslation { Norwegian }  { keythms_listof_title } { Liste~over~teoremer }
        \ProvideTranslation { Norwegian }  { keythms_continues }    { fortsetter~fra~side~ }
        \ProvideTranslation { Norwegian }  { keythms_axiom }        { Aksiom }
        \ProvideTranslation { Norwegian }  { keythms_conjecture }   { Formodning }
        \ProvideTranslation { Norwegian }  { keythms_corollary }    { Korollar }
        \ProvideTranslation { Norwegian }  { keythms_definition }   { Definisjon }
        \ProvideTranslation { Norwegian }  { keythms_example }      { Eksempel }
        \ProvideTranslation { Norwegian }  { keythms_lemma }        { Lemma }
        \ProvideTranslation { Norwegian }  { keythms_proposition }  { Påstand }
        \ProvideTranslation { Norwegian }  { keythms_remark }       { Bemerkning }
        \ProvideTranslation { Norwegian }  { keythms_theorem }      { Teorem }
        \ProvideTranslation { Polish }     { keythms_listof_title } { Lista~twierdzeń }
        \ProvideTranslation { Polish }     { keythms_continues }    { ciąg~dalszy~ze~strony~ }
        \ProvideTranslation { Portuguese } { keythms_listof_title } { Lista~de~teoremas }
        \ProvideTranslation { Portuguese } { keythms_continues }    { continua~da~p.\, }
        \ProvideTranslation { Portuguese } { keythms_axiom }        { Axioma }
        \ProvideTranslation { Portuguese } { keythms_conjecture }   { Conjetura }
        \ProvideTranslation { Portuguese } { keythms_corollary }    { Corolário }
        \ProvideTranslation { Portuguese } { keythms_definition }   { Definição }
        \ProvideTranslation { Portuguese } { keythms_example }      { Exemplo }
        \ProvideTranslation { Portuguese } { keythms_lemma }        { Lema }
        \ProvideTranslation { Portuguese } { keythms_proposition }  { Proposição }
        \ProvideTranslation { Portuguese } { keythms_remark }       { Observação }
        \ProvideTranslation { Portuguese } { keythms_theorem }      { Teorema }
        \ProvideTranslation { Romanian }   { keythms_listof_title } { Lista~teoremelor }
        \ProvideTranslation { Romanian }   { keythms_continues }    { continuare~de~la~p.\, }
        \ProvideTranslation { Russian }    { keythms_listof_title } { Список~теорем }
        \ProvideTranslation { Slovak }     { keythms_listof_title } { Zoznam~teorém }
        \ProvideTranslation { Slovak }     { keythms_continues }    { pokračovanie~zo~strany~ }
        \ProvideTranslation { Slovenian }  { keythms_listof_title } { Seznam~trditev }
        \ProvideTranslation { Slovenian }  { keythms_continues }    { nadaljevanje~s~strani~ }
        \ProvideTranslation { Spanish }    { keythms_listof_title } { Lista~de~teoremas }
        \ProvideTranslation { Spanish }    { keythms_continues }    { continúa~de~la~p.\, }
        \ProvideTranslation { Spanish }    { keythms_axiom }        { Axioma }
        \ProvideTranslation { Spanish }    { keythms_conjecture }   { Conjetura }
        \ProvideTranslation { Spanish }    { keythms_corollary }    { Corolario }
        \ProvideTranslation { Spanish }    { keythms_definition }   { Definición }
        \ProvideTranslation { Spanish }    { keythms_example }      { Ejemplo }
        \ProvideTranslation { Spanish }    { keythms_lemma }        { Lema }
        \ProvideTranslation { Spanish }    { keythms_proposition }  { Proposición }
        \ProvideTranslation { Spanish }    { keythms_remark }       { Observación }
        \ProvideTranslation { Spanish }    { keythms_theorem }      { Teorema }
        \ProvideTranslation { Swedish }    { keythms_listof_title } { Lista~över~teorem }
        \ProvideTranslation { Swedish }    { keythms_continues }    { fortsättning~från~sidan~ }
        \ProvideTranslation { Swedish }    { keythms_axiom }        { Axiom }
        \ProvideTranslation { Swedish }    { keythms_conjecture }   { Förmodan }
        \ProvideTranslation { Swedish }    { keythms_corollary }    { Följdsats }
        \ProvideTranslation { Swedish }    { keythms_definition }   { Definition }
        \ProvideTranslation { Swedish }    { keythms_example }      { Exempel }
        \ProvideTranslation { Swedish }    { keythms_lemma }        { Hjälpsats }
        \ProvideTranslation { Swedish }    { keythms_proposition }  { Påstående }
        \ProvideTranslation { Swedish }    { keythms_remark }       { Anmärkning }
        \ProvideTranslation { Swedish }    { keythms_theorem }      { Sats }
        \ProvideTranslation { Turkish }    { keythms_listof_title } { Teoremler~Listesi }
        \ProvideTranslation { Ukrainian }  { keythms_listof_title } { Список~теорем }
        \ProvideTranslation { Welsh }      { keythms_listof_title } { Rhestr~o~Theoremau }
        \ProvideTranslation { Welsh }      { keythms_continues }    { yn~parhau~o~dudalen~ }
      }
  }
\hook_gput_code:nnn { begindocument/before } { . }
  { \tl_use:N \c__keythms_translationsetup_tl }

\keys_define:nn { keytheorems/predefined }
  {
    parent       .tl_gset:N        = \g__keythms_predefined_parent_tl,
    parent       .value_required:n = true,
    parent       .usage:n          = preamble,
    siblings     .bool_gset:N      = \g__keythms_predefined_siblings_bool,
    siblings     .initial:n        = true,
    siblings     .usage:n          = preamble,
    sharenumbers .bool_gset:N      = \g__keythms_predefined_siblings_bool,
    sharenumbers .initial:n        = true,
    sharenumbers .usage:n          = preamble,
  }
\cs_generate_variant:Nn \keythms_thm_providekeythm:nn { ne }
\tl_const:Nn \c__keythms_predefinedsetup_tl
  { % ^ translations doesn't set current lang until begindocument/before
    \bool_if:NT \g__keythms_predefined_bool
      {
        \bool_if:NT \g__keythms_autotranslate_bool
          { % nil lang treated same as english
            \str_if_eq:VnF \languagename { nil }
              { % ^ need str test, not tl; see babel note about \languagename
                \IfTranslation { \languagename } { keythms_theorem } { }
                  {
                    \msg_warning:nne { keytheorems }
                      { no-predefined-translations } { \languagename }
                  }
              }
          }
        \tl_clear:N \l__keythms_tmpa_tl
        \tl_clear:N \l__keythms_tmpb_tl
        \tl_if_empty:NF \g__keythms_predefined_parent_tl
          {
            \tl_set:Nn \l__keythms_tmpa_tl
              { parent = \g__keythms_predefined_parent_tl, }
            % this might be overwritten in next step
            \tl_set_eq:NN \l__keythms_tmpb_tl \l__keythms_tmpa_tl
          }
        \bool_if:NT \g__keythms_predefined_siblings_bool
          {
            \tl_set:Nn \l__keythms_tmpb_tl
              { sibling=theorem, }
          }
        % explicit style=plain necessary so we don't pick up \theoremstyle
        \keythms_thm_providekeythm:ne { theorem }
          {
            name  = \GetTranslation{keythms_theorem},
            style = plain,
            \l__keythms_tmpa_tl
          }
        \clist_map_inline:nn { conjecture, corollary, lemma, proposition }
          {
            \keythms_thm_providekeythm:ne { #1 }
              {
                name  = \GetTranslation{keythms_#1},
                style = plain,
                \l__keythms_tmpb_tl
              }
          }
        \clist_map_inline:nn { axiom, definition, example }
          {
            \keythms_thm_providekeythm:ne { #1 }
              {
                name  = \GetTranslation{keythms_#1},
                style = definition,
                \l__keythms_tmpb_tl
              }
          }
        \keythms_thm_providekeythm:ne { remark }
          {
            name  = \GetTranslation{keythms_remark},
            style = remark,
            \l__keythms_tmpb_tl
          }
      }
  }
\hook_gput_code:nnn { begindocument } { . }
  { \tl_use:N \c__keythms_predefinedsetup_tl }

\ProcessKeyOptions[keytheorems]

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Support for non-default classes %%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\tl_const:Nn \c__keythms_support_AMSshared_tl
  {
    \keys_define:nn { keytheorems/listof } % adjust to AMS classes
      {
        indent     .initial:n = 0pt,
        numwidth   .initial:n = 1.5pc,
        title-code .code:n    =
          { % warn but set titlecmd just in case
            \msg_warning:nn { keytheorems } { title-code-with-AMS }
            \cs_set_protected:Npn \__keythms_listof_titlecmd:n ##1 { #1 }
          },
      }
    \RenewDocumentCommand \listofkeytheorems { +O{} }
      { % title command not customizable here
        \bool_gset_true:N \g__keythms_listof_writefile_bool
        \group_begin:
        \keys_set:nn { keytheorems/listof } { #1 }
        \cs_set_protected:Npn \KeyThmsContentsLine ##1 { ##1 }
        \bool_if:NF \l__keythms_listof_nochapskip_bool
          {
            \cs_set_protected:Npn \KeyThmsAddvspace { \addvspace }
          }
        \bool_if:NT \l__keythms_listof_onecol_bool
          { % actually check if setting \onecolumn is necessary
            \legacy_if:nT { @twocolumn }
              {
                \onecolumn
                \cs_set_protected:Npn \__keythms_listof_twocolreset: { \twocolumn }
              }
          }
        \bool_if:NT \l__keythms_listof_swapnumber_bool
          {
            \cs_set:Npn \__keythms_listof_misdirect:nnn ##1##2##3
              { ##1 ~ ##2##3 }
          }
        \legacy_if_set_false:n { @filesw }
        \bool_if:NTF \l__keythms_listof_notitle_bool
          { % hacky!
            \cs_set_eq:NN \@startsection \use_none:nnnnnnn
            \@starttoc{ thlist }{ }
          }
          { % ams classes don't expand title enough
            \protected@edef \l__keythms_tmpa_tl { \l__keythms_listof_title_tl }
            \bool_if:NT \l__keythms_listof_notoc_bool
              { \cs_set_eq:NN \addcontentsline \use_none:nnn } % hacky!
            \@starttoc{ thlist }{ \l__keythms_tmpa_tl }
          }
        \__keythms_listof_twocolreset:
        \group_end:
      }
    \cs_new:Npn \__keythms_listof_ams_tocline:
      {
        \@tocline{ 0 }{ 3pt plus 2pt }{ \l__keythms_listof_indent_dim }
          { \l__keythms_listof_numwidth_dim }{ }
      }
    \cs_set_eq:NN \keythms_listof_tocline: \__keythms_listof_ams_tocline:
  }

\prg_new_conditional:Npnn \__keythms_if_classloaded:n #1 { p }
  {
    \IfClassLoadedTF { #1 } { \prg_return_true: } { \prg_return_false: }
  }

\cs_new_protected:Npn \__keythms_support_input:n #1
  {
    \file_input:n { class-support/keythms-#1-support }
  }

% acmart and aomart defaults also handled in amsart support file
\bool_case:n
  {
    { \__keythms_if_classloaded_p:n { amsart } }
      { \__keythms_support_input:n { amsart } }
    { \__keythms_if_classloaded_p:n { amsbook } }
      { \__keythms_support_input:n { amsbook } }
    { \__keythms_if_classloaded_p:n { amsproc } }
      { \__keythms_support_input:n { amsproc } }
    { \__keythms_if_classloaded_p:n { beamer } }
      { \__keythms_support_input:n { beamer } }
    { \__keythms_if_classloaded_p:n { IEEEtran } }
      { \__keythms_support_input:n { IEEEtran } }
    { \__keythms_if_classloaded_p:n { jlreq } }
      { \__keythms_support_input:n { jlreq } }
    { \__keythms_if_classloaded_p:n { ltx-talk } }
      { \__keythms_support_input:n { ltx-talk } }
    { \__keythms_if_classloaded_p:n { memoir } }
      { \__keythms_support_input:n { memoir } }
  }

% now deal with font packages that change plain style
\cs_new_protected:Npn \__keythms_support_fontpkg:nn #1#2
  {
    \clist_map_inline:nn { #1 }
      {
        \hook_gput_code:nnn { package/##1/after } { . }
          {
            \IfPackageLoadedWithOptionsT { ##1 } { theoremfont }
              {
                \prop_gput_from_keyval:Nn \g__keythms_thmstyle_defaultkeys_prop { #2 }
                \keys_precompile:neN { keytheorems/thmstyle }
                  { \prop_to_keyval:N \g__keythms_thmstyle_defaultkeys_prop }
                  \l__keythms_thmstyle_defaultkeys_tl
              }
          }
      }
  }

\__keythms_support_fontpkg:nn { baskervillef,cochineal,stickstootext } { bodyfont = \slshape }
\__keythms_support_fontpkg:nn { libertinust1math,newpxtext,newtxtext,XCharter }
  {
    bodyfont   = \thfamily,
    spaceabove = \medskipamount,
    spacebelow = \medskipamount,
  }
\__keythms_support_fontpkg:nn { scholax } { bodyfont = \thfamily }

%%%%%%%%%%%%%%%%%%%%%%%
%%% Tagging Support %%%
%%%%%%%%%%%%%%%%%%%%%%%

\prg_new_conditional:Npnn \__keythms_if_formatatleast:n #1 { p }
  {
    \IfFormatAtLeastTF { #1 } { \prg_return_true: } { \prg_return_false: }
  }
\IfDocumentMetadataTF
  {
    \bool_lazy_or:nnT
      { \tag_if_active_p: }
      { \__keythms_if_formatatleast_p:n { 2025-11-01 } }
      {
        \msg_new:nnn { keytheorems } { tag-incompat-key }
          {
            The~key~'#1'~does~not~currently~work~with~
            tagging.~Ignoring~this~key~\msg_line_context:.
          }
        \keys_define:nn { keytheorems/thm }
          {
            tcolorbox .code:n =
              {
                \msg_warning:nnn { keytheorems } { tag-incompat-key }
                  { tcolorbox }
              },
            tcolorbox-no-titlebar .code:n =
              {
                \msg_warning:nnn { keytheorems } { tag-incompat-key }
                  { tcolorbox-no-titlebar }
              },
          }
        \bool_lazy_any:nF
          {
            { \__keythms_if_classloaded_p:n { amsart } }
            { \__keythms_if_classloaded_p:n { amsbook } }
            { \__keythms_if_classloaded_p:n { amsproc } }
          }
          { % only redefine \@starttoc with print-body when AMS class not loaded
            \keys_define:nn { keytheorems/listof }
              {
                print-body .code:n =
                  {
                    \cs_set_protected:Nn \keythms_listof_listcmd:nnnnnnn
                      {
                        \tl_if_empty:nF { ##7 }
                          {
                            \keythms_getthm_theorem:nnnnn
                              {##1}{##2}{##5}{##6}{##7}
                          }
                      }
                    % with tagging, make \@starttoc same as input
                    \cs_set_protected:Npn \@starttoc ##1
                      { \makeatletter \@input { \jobname.##1 } }
                  },
              }
          }
        \IfFormatAtLeastTF { 2025-06-01 }
          { % dev formats use theoremblock instance
            \tl_const:Nn \c__keythms_tagging_instance_tl { theoremblock-0 }
          }
          { % current format uses displayblock instance
            \tl_const:Nn \c__keythms_tagging_instance_tl { displayblock-0 }
          }
        \IfFormatAtLeastTF { 2025-11-01 }
          { % dev formats changed the name of the keys to left-margin, etc.
            \cs_set_protected:Npn \__keythms_thm_margincode:nnn #1#2#3
              { % tagging code does not define theorems with lists
                \tl_gput_right:cn { g__keythms_thm_preheadfromkeys_#1_tl }
                  {
                    \exp_args:Nne \EditInstance { block }
                      { \c__keythms_tagging_instance_tl }
                      {
                        left-margin = #2,
                        right-margin = #3,
                      }
                    % hack until https://github.com/latex3/tagging-project/issues/755 is fixed
                    \EditInstance { block } { listblock-1 } { right-margin = 0pt }
                  }
              }
          }
          {
            \cs_set_protected:Npn \__keythms_thm_margincode:nnn #1#2#3
              { % tagging code does not define theorems with lists
                \tl_gput_right:cn { g__keythms_thm_preheadfromkeys_#1_tl }
                  {
                    \exp_args:Nne \EditInstance { block }
                      { \c__keythms_tagging_instance_tl }
                      {
                        leftmargin = #2,
                        rightmargin = #3,
                      }
                    % hack until https://github.com/latex3/tagging-project/issues/755 is fixed
                    \EditInstance { block } { list-1 } { rightmargin = 0pt }
                  }
              }
          }
      }
  }
  { }

\file_input_stop:
